1#![no_std]
3#![doc(
4 html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg",
5 html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg",
6 html_root_url = "https://docs.rs/dbl/0.3.2"
7)]
8#![forbid(unsafe_code)]
9
10extern crate generic_array;
11
12use generic_array::typenum::{U16, U32, U8};
13use generic_array::GenericArray;
14
15use core::convert::TryInto;
16
17const C64: u64 = 0b1_1011;
18const C128: u64 = 0b1000_0111;
19const C256: u64 = 0b100_0010_0101;
20
21pub trait Dbl {
26 fn dbl(self) -> Self;
33
34 fn inv_dbl(self) -> Self;
39}
40
41impl Dbl for GenericArray<u8, U8> {
42 #[inline]
43 fn dbl(self) -> Self {
44 let mut val = u64::from_be_bytes(self.into());
45
46 let a = val >> 63;
47 val <<= 1;
48 val ^= a * C64;
49
50 val.to_be_bytes().into()
51 }
52
53 #[inline]
54 fn inv_dbl(self) -> Self {
55 let mut val = u64::from_be_bytes(self.into());
56
57 let a = val & 1;
58 val >>= 1;
59 val ^= a * ((1 << 63) ^ (C64 >> 1));
60
61 val.to_be_bytes().into()
62 }
63}
64
65impl Dbl for GenericArray<u8, U16> {
66 #[inline]
67 fn dbl(self) -> Self {
68 let mut val = [
69 u64::from_be_bytes(self[..8].try_into().unwrap()),
70 u64::from_be_bytes(self[8..].try_into().unwrap()),
71 ];
72
73 let b = val[1] >> 63;
74 let a = val[0] >> 63;
75
76 val[0] <<= 1;
77 val[0] ^= b;
78 val[1] <<= 1;
79 val[1] ^= a * C128;
80
81 let mut res = Self::default();
82 res[..8].copy_from_slice(&val[0].to_be_bytes());
83 res[8..].copy_from_slice(&val[1].to_be_bytes());
84 res
85 }
86
87 #[inline]
88 fn inv_dbl(self) -> Self {
89 let mut val = [
90 u64::from_be_bytes(self[..8].try_into().unwrap()),
91 u64::from_be_bytes(self[8..].try_into().unwrap()),
92 ];
93
94 let a = (val[0] & 1) << 63;
95 let b = val[1] & 1;
96
97 val[0] >>= 1;
98 val[1] >>= 1;
99 val[1] ^= a;
100 val[0] ^= b * (1 << 63);
101 val[1] ^= b * (C128 >> 1);
102
103 let mut res = Self::default();
104 res[..8].copy_from_slice(&val[0].to_be_bytes());
105 res[8..].copy_from_slice(&val[1].to_be_bytes());
106 res
107 }
108}
109
110impl Dbl for GenericArray<u8, U32> {
111 #[inline]
112 fn dbl(self) -> Self {
113 let mut val = [
114 u64::from_be_bytes(self[0..8].try_into().unwrap()),
115 u64::from_be_bytes(self[8..16].try_into().unwrap()),
116 u64::from_be_bytes(self[16..24].try_into().unwrap()),
117 u64::from_be_bytes(self[24..32].try_into().unwrap()),
118 ];
119
120 let a = val[0] >> 63;
121 let b = val[1] >> 63;
122 let c = val[2] >> 63;
123 let d = val[3] >> 63;
124
125 val[0] <<= 1;
126 val[0] ^= b;
127 val[1] <<= 1;
128 val[1] ^= c;
129 val[2] <<= 1;
130 val[2] ^= d;
131 val[3] <<= 1;
132 val[3] ^= a * C256;
133
134 let mut res = Self::default();
135 res[0..8].copy_from_slice(&val[0].to_be_bytes());
136 res[8..16].copy_from_slice(&val[1].to_be_bytes());
137 res[16..24].copy_from_slice(&val[2].to_be_bytes());
138 res[24..32].copy_from_slice(&val[3].to_be_bytes());
139 res
140 }
141
142 #[inline]
143 fn inv_dbl(self) -> Self {
144 let mut val = [
145 u64::from_be_bytes(self[0..8].try_into().unwrap()),
146 u64::from_be_bytes(self[8..16].try_into().unwrap()),
147 u64::from_be_bytes(self[16..24].try_into().unwrap()),
148 u64::from_be_bytes(self[24..32].try_into().unwrap()),
149 ];
150
151 let a = (val[0] & 1) << 63;
152 let b = (val[1] & 1) << 63;
153 let c = (val[2] & 1) << 63;
154 let d = val[3] & 1;
155
156 val[0] >>= 1;
157 val[1] >>= 1;
158 val[2] >>= 1;
159 val[3] >>= 1;
160 val[1] ^= a;
161 val[2] ^= b;
162 val[3] ^= c;
163
164 val[0] ^= d * (1 << 63);
165 val[3] ^= d * (C256 >> 1);
166
167 let mut res = Self::default();
168 res[0..8].copy_from_slice(&val[0].to_be_bytes());
169 res[8..16].copy_from_slice(&val[1].to_be_bytes());
170 res[16..24].copy_from_slice(&val[2].to_be_bytes());
171 res[24..32].copy_from_slice(&val[3].to_be_bytes());
172 res
173 }
174}