|
| 1 | +use elliptic_curve::bigint::{ArrayEncoding, U384}; |
| 2 | +use elliptic_curve::consts::U72; |
| 3 | +use elliptic_curve::generic_array::GenericArray; |
| 4 | +use elliptic_curve::hash2curve::{ |
| 5 | + FromOkm, GroupDigest, MapToCurve, OsswuMap, OsswuMapParams, Sgn0, |
| 6 | +}; |
| 7 | +use elliptic_curve::ops::Reduce; |
| 8 | +use elliptic_curve::subtle::Choice; |
| 9 | +use elliptic_curve::DecompressPoint; |
| 10 | + |
| 11 | +use crate::{AffinePoint, NistP384, ProjectivePoint, Scalar}; |
| 12 | + |
| 13 | +use super::FieldElement; |
| 14 | + |
| 15 | +impl GroupDigest for NistP384 { |
| 16 | + type FieldElement = FieldElement; |
| 17 | +} |
| 18 | + |
| 19 | +impl FromOkm for FieldElement { |
| 20 | + type Length = U72; |
| 21 | + |
| 22 | + fn from_okm(data: &GenericArray<u8, Self::Length>) -> Self { |
| 23 | + const F_2_288: FieldElement = FieldElement::from_be_hex( |
| 24 | + "000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000", |
| 25 | + ); |
| 26 | + let mut d0 = GenericArray::default(); |
| 27 | + d0[12..].copy_from_slice(&data[0..36]); |
| 28 | + let d0 = FieldElement::from_uint_unchecked(U384::from_be_byte_array(d0)); |
| 29 | + |
| 30 | + let mut d1 = GenericArray::default(); |
| 31 | + d1[12..].copy_from_slice(&data[36..]); |
| 32 | + let d1 = FieldElement::from_uint_unchecked(U384::from_be_byte_array(d1)); |
| 33 | + |
| 34 | + d0 * F_2_288 + d1 |
| 35 | + } |
| 36 | +} |
| 37 | + |
| 38 | +impl Sgn0 for FieldElement { |
| 39 | + fn sgn0(&self) -> Choice { |
| 40 | + self.is_odd() |
| 41 | + } |
| 42 | +} |
| 43 | + |
| 44 | +impl OsswuMap for FieldElement { |
| 45 | + const PARAMS: OsswuMapParams<Self> = OsswuMapParams { |
| 46 | + c1: &[ |
| 47 | + 0x0000_0000_3fff_ffff, |
| 48 | + 0xbfff_ffff_c000_0000, |
| 49 | + 0xffff_ffff_ffff_ffff, |
| 50 | + 0xffff_ffff_ffff_ffff, |
| 51 | + 0xffff_ffff_ffff_ffff, |
| 52 | + 0x3fff_ffff_ffff_ffff, |
| 53 | + ], |
| 54 | + c2: FieldElement::from_be_hex( |
| 55 | + "019877cc1041b7555743c0ae2e3a3e61fb2aaa2e0e87ea557a563d8b598a0940d0a697a9e0b9e92cfaa314f583c9d066", |
| 56 | + ), |
| 57 | + map_a: FieldElement::from_be_hex( |
| 58 | + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffc", |
| 59 | + ), |
| 60 | + map_b: FieldElement::from_be_hex( |
| 61 | + "b3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef", |
| 62 | + ), |
| 63 | + z: FieldElement::from_be_hex( |
| 64 | + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffff3", |
| 65 | + ), |
| 66 | + }; |
| 67 | +} |
| 68 | + |
| 69 | +impl MapToCurve for FieldElement { |
| 70 | + type Output = ProjectivePoint; |
| 71 | + |
| 72 | + fn map_to_curve(&self) -> Self::Output { |
| 73 | + let (qx, qy) = self.osswu(); |
| 74 | + |
| 75 | + // TODO(tarcieri): assert that `qy` is correct? less circuitous conversion? |
| 76 | + AffinePoint::decompress(&qx.to_sec1(), qy.is_odd()) |
| 77 | + .unwrap() |
| 78 | + .into() |
| 79 | + } |
| 80 | +} |
| 81 | + |
| 82 | +impl FromOkm for Scalar { |
| 83 | + type Length = U72; |
| 84 | + |
| 85 | + fn from_okm(data: &GenericArray<u8, Self::Length>) -> Self { |
| 86 | + const F_2_288: Scalar = Scalar::from_be_hex( |
| 87 | + "000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000", |
| 88 | + ); |
| 89 | + |
| 90 | + let mut d0 = GenericArray::default(); |
| 91 | + d0[12..].copy_from_slice(&data[0..36]); |
| 92 | + let d0 = Scalar::from_be_bytes_reduced(d0); |
| 93 | + |
| 94 | + let mut d1 = GenericArray::default(); |
| 95 | + d1[12..].copy_from_slice(&data[36..]); |
| 96 | + let d1 = Scalar::from_be_bytes_reduced(d1); |
| 97 | + |
| 98 | + d0 * F_2_288 + d1 |
| 99 | + } |
| 100 | +} |
| 101 | + |
| 102 | +#[cfg(test)] |
| 103 | +mod tests { |
| 104 | + use crate::arithmetic::FieldElement; |
| 105 | + use crate::{NistP384, Scalar}; |
| 106 | + use elliptic_curve::bigint::{ArrayEncoding, NonZero, U384, U576}; |
| 107 | + use elliptic_curve::consts::U72; |
| 108 | + use elliptic_curve::generic_array::GenericArray; |
| 109 | + use elliptic_curve::group::cofactor::CofactorGroup; |
| 110 | + use elliptic_curve::hash2curve::{self, ExpandMsgXmd, FromOkm, GroupDigest, MapToCurve}; |
| 111 | + use elliptic_curve::ops::Reduce; |
| 112 | + use elliptic_curve::sec1::{self, ToEncodedPoint}; |
| 113 | + use elliptic_curve::Curve; |
| 114 | + use hex_literal::hex; |
| 115 | + use proptest::num::u64::ANY; |
| 116 | + use proptest::{prelude::ProptestConfig, proptest}; |
| 117 | + use sha2::Sha384; |
| 118 | + |
| 119 | + #[test] |
| 120 | + fn hash_to_curve() { |
| 121 | + struct TestVector { |
| 122 | + msg: &'static [u8], |
| 123 | + p_x: [u8; 48], |
| 124 | + p_y: [u8; 48], |
| 125 | + u_0: [u8; 48], |
| 126 | + u_1: [u8; 48], |
| 127 | + q0_x: [u8; 48], |
| 128 | + q0_y: [u8; 48], |
| 129 | + q1_x: [u8; 48], |
| 130 | + q1_y: [u8; 48], |
| 131 | + } |
| 132 | + |
| 133 | + const DST: &[u8] = b"QUUX-V01-CS02-with-P384_XMD:SHA-384_SSWU_RO_"; |
| 134 | + |
| 135 | + const TEST_VECTORS: &[TestVector] = &[ |
| 136 | + TestVector { |
| 137 | + msg: b"", |
| 138 | + p_x: hex!("eb9fe1b4f4e14e7140803c1d99d0a93cd823d2b024040f9c067a8eca1f5a2eeac9ad604973527a356f3fa3aeff0e4d83"), |
| 139 | + p_y: hex!("0c21708cff382b7f4643c07b105c2eaec2cead93a917d825601e63c8f21f6abd9abc22c93c2bed6f235954b25048bb1a"), |
| 140 | + u_0: hex!("25c8d7dc1acd4ee617766693f7f8829396065d1b447eedb155871feffd9c6653279ac7e5c46edb7010a0e4ff64c9f3b4"), |
| 141 | + u_1: hex!("59428be4ed69131df59a0c6a8e188d2d4ece3f1b2a3a02602962b47efa4d7905945b1e2cc80b36aa35c99451073521ac"), |
| 142 | + q0_x: hex!("e4717e29eef38d862bee4902a7d21b44efb58c464e3e1f0d03894d94de310f8ffc6de86786dd3e15a1541b18d4eb2846"), |
| 143 | + q0_y: hex!("6b95a6e639822312298a47526bb77d9cd7bcf76244c991c8cd70075e2ee6e8b9a135c4a37e3c0768c7ca871c0ceb53d4"), |
| 144 | + q1_x: hex!("509527cfc0750eedc53147e6d5f78596c8a3b7360e0608e2fab0563a1670d58d8ae107c9f04bcf90e89489ace5650efd"), |
| 145 | + q1_y: hex!("33337b13cb35e173fdea4cb9e8cce915d836ff57803dbbeb7998aa49d17df2ff09b67031773039d09fbd9305a1566bc4"), |
| 146 | + }, |
| 147 | + TestVector { |
| 148 | + msg: b"abc", |
| 149 | + p_x: hex!("e02fc1a5f44a7519419dd314e29863f30df55a514da2d655775a81d413003c4d4e7fd59af0826dfaad4200ac6f60abe1"), |
| 150 | + p_y: hex!("01f638d04d98677d65bef99aef1a12a70a4cbb9270ec55248c04530d8bc1f8f90f8a6a859a7c1f1ddccedf8f96d675f6"), |
| 151 | + u_0: hex!("53350214cb6bef0b51abb791b1c4209a2b4c16a0c67e1ab1401017fad774cd3b3f9a8bcdf7f6229dd8dd5a075cb149a0"), |
| 152 | + u_1: hex!("c0473083898f63e03f26f14877a2407bd60c75ad491e7d26cbc6cc5ce815654075ec6b6898c7a41d74ceaf720a10c02e"), |
| 153 | + q0_x: hex!("fc853b69437aee9a19d5acf96a4ee4c5e04cf7b53406dfaa2afbdd7ad2351b7f554e4bbc6f5db4177d4d44f933a8f6ee"), |
| 154 | + q0_y: hex!("7e042547e01834c9043b10f3a8221c4a879cb156f04f72bfccab0c047a304e30f2aa8b2e260d34c4592c0c33dd0c6482"), |
| 155 | + q1_x: hex!("57912293709b3556b43a2dfb137a315d256d573b82ded120ef8c782d607c05d930d958e50cb6dc1cc480b9afc38c45f1"), |
| 156 | + q1_y: hex!("de9387dab0eef0bda219c6f168a92645a84665c4f2137c14270fb424b7532ff84843c3da383ceea24c47fa343c227bb8"), |
| 157 | + }, |
| 158 | + TestVector { |
| 159 | + msg: b"abcdef0123456789", |
| 160 | + p_x: hex!("bdecc1c1d870624965f19505be50459d363c71a699a496ab672f9a5d6b78676400926fbceee6fcd1780fe86e62b2aa89"), |
| 161 | + p_y: hex!("57cf1f99b5ee00f3c201139b3bfe4dd30a653193778d89a0accc5e0f47e46e4e4b85a0595da29c9494c1814acafe183c"), |
| 162 | + u_0: hex!("aab7fb87238cf6b2ab56cdcca7e028959bb2ea599d34f68484139dde85ec6548a6e48771d17956421bdb7790598ea52e"), |
| 163 | + u_1: hex!("26e8d833552d7844d167833ca5a87c35bcfaa5a0d86023479fb28e5cd6075c18b168bf1f5d2a0ea146d057971336d8d1"), |
| 164 | + q0_x: hex!("0ceece45b73f89844671df962ad2932122e878ad2259e650626924e4e7f132589341dec1480ebcbbbe3509d11fb570b7"), |
| 165 | + q0_y: hex!("fafd71a3115298f6be4ae5c6dfc96c400cfb55760f185b7b03f3fa45f3f91eb65d27628b3c705cafd0466fafa54883ce"), |
| 166 | + q1_x: hex!("dea1be8d3f9be4cbf4fab9d71d549dde76875b5d9b876832313a083ec81e528cbc2a0a1d0596b3bcb0ba77866b129776"), |
| 167 | + q1_y: hex!("eb15fe71662214fb03b65541f40d3eb0f4cf5c3b559f647da138c9f9b7484c48a08760e02c16f1992762cb7298fa52cf"), |
| 168 | + }, |
| 169 | + TestVector { |
| 170 | + msg: b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", |
| 171 | + p_x: hex!("03c3a9f401b78c6c36a52f07eeee0ec1289f178adf78448f43a3850e0456f5dd7f7633dd31676d990eda32882ab486c0"), |
| 172 | + p_y: hex!("cc183d0d7bdfd0a3af05f50e16a3f2de4abbc523215bf57c848d5ea662482b8c1f43dc453a93b94a8026db58f3f5d878"), |
| 173 | + u_0: hex!("04c00051b0de6e726d228c85bf243bf5f4789efb512b22b498cde3821db9da667199b74bd5a09a79583c6d353a3bb41c"), |
| 174 | + u_1: hex!("97580f218255f899f9204db64cd15e6a312cb4d8182375d1e5157c8f80f41d6a1a4b77fb1ded9dce56c32058b8d5202b"), |
| 175 | + q0_x: hex!("051a22105e0817a35d66196338c8d85bd52690d79bba373ead8a86dd9899411513bb9f75273f6483395a7847fb21edb4"), |
| 176 | + q0_y: hex!("f168295c1bbcff5f8b01248e9dbc885335d6d6a04aea960f7384f746ba6502ce477e624151cc1d1392b00df0f5400c06"), |
| 177 | + q1_x: hex!("6ad7bc8ed8b841efd8ad0765c8a23d0b968ec9aa360a558ff33500f164faa02bee6c704f5f91507c4c5aad2b0dc5b943"), |
| 178 | + q1_y: hex!("47313cc0a873ade774048338fc34ca5313f96bbf6ae22ac6ef475d85f03d24792dc6afba8d0b4a70170c1b4f0f716629"), |
| 179 | + }, |
| 180 | + TestVector { |
| 181 | + msg: b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", |
| 182 | + p_x: hex!("7b18d210b1f090ac701f65f606f6ca18fb8d081e3bc6cbd937c5604325f1cdea4c15c10a54ef303aabf2ea58bd9947a4"), |
| 183 | + p_y: hex!("ea857285a33abb516732915c353c75c576bf82ccc96adb63c094dde580021eddeafd91f8c0bfee6f636528f3d0c47fd2"), |
| 184 | + u_0: hex!("480cb3ac2c389db7f9dac9c396d2647ae946db844598971c26d1afd53912a1491199c0a5902811e4b809c26fcd37a014"), |
| 185 | + u_1: hex!("d28435eb34680e148bf3908536e42231cba9e1f73ae2c6902a222a89db5c49c97db2f8fa4d4cd6e424b17ac60bdb9bb6"), |
| 186 | + q0_x: hex!("42e6666f505e854187186bad3011598d9278b9d6e3e4d2503c3d236381a56748dec5d139c223129b324df53fa147c4df"), |
| 187 | + q0_y: hex!("8ee51dbda46413bf621838cc935d18d617881c6f33f3838a79c767a1e5618e34b22f79142df708d2432f75c7366c8512"), |
| 188 | + q1_x: hex!("4ff01ceeba60484fa1bc0d825fe1e5e383d8f79f1e5bb78e5fb26b7a7ef758153e31e78b9d60ce75c5e32e43869d4e12"), |
| 189 | + q1_y: hex!("0f84b978fac8ceda7304b47e229d6037d32062e597dc7a9b95bcd9af441f3c56c619a901d21635f9ec6ab4710b9fcd0e"), |
| 190 | + }, |
| 191 | + ]; |
| 192 | + |
| 193 | + for test_vector in TEST_VECTORS { |
| 194 | + // in parts |
| 195 | + let mut u = [FieldElement::default(), FieldElement::default()]; |
| 196 | + hash2curve::hash_to_field::<ExpandMsgXmd<Sha384>, FieldElement>( |
| 197 | + &[test_vector.msg], |
| 198 | + DST, |
| 199 | + &mut u, |
| 200 | + ) |
| 201 | + .unwrap(); |
| 202 | + |
| 203 | + /// Assert that the provided projective point matches the given test vector. |
| 204 | + // TODO(tarcieri): use coordinate APIs. See zkcrypto/group#30 |
| 205 | + macro_rules! assert_point_eq { |
| 206 | + ($actual:expr, $expected_x:expr, $expected_y:expr) => { |
| 207 | + let point = $actual.to_affine().to_encoded_point(false); |
| 208 | + let (actual_x, actual_y) = match point.coordinates() { |
| 209 | + sec1::Coordinates::Uncompressed { x, y } => (x, y), |
| 210 | + _ => unreachable!(), |
| 211 | + }; |
| 212 | + |
| 213 | + assert_eq!(&$expected_x, actual_x.as_slice()); |
| 214 | + assert_eq!(&$expected_y, actual_y.as_slice()); |
| 215 | + }; |
| 216 | + } |
| 217 | + |
| 218 | + assert_eq!(u[0].to_sec1().as_slice(), test_vector.u_0); |
| 219 | + assert_eq!(u[1].to_sec1().as_slice(), test_vector.u_1); |
| 220 | + |
| 221 | + let q0 = u[0].map_to_curve(); |
| 222 | + assert_point_eq!(q0, test_vector.q0_x, test_vector.q0_y); |
| 223 | + |
| 224 | + let q1 = u[1].map_to_curve(); |
| 225 | + assert_point_eq!(q1, test_vector.q1_x, test_vector.q1_y); |
| 226 | + |
| 227 | + let p = q0.clear_cofactor() + q1.clear_cofactor(); |
| 228 | + assert_point_eq!(p, test_vector.p_x, test_vector.p_y); |
| 229 | + |
| 230 | + // complete run |
| 231 | + let pt = |
| 232 | + NistP384::hash_from_bytes::<ExpandMsgXmd<Sha384>>(&[test_vector.msg], DST).unwrap(); |
| 233 | + assert_point_eq!(pt, test_vector.p_x, test_vector.p_y); |
| 234 | + } |
| 235 | + } |
| 236 | + |
| 237 | + /// Taken from <https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-16.html#name-oprfp-384-sha-384-2>. |
| 238 | + #[test] |
| 239 | + fn hash_to_scalar_voprf() { |
| 240 | + struct TestVector { |
| 241 | + dst: &'static [u8], |
| 242 | + key_info: &'static [u8], |
| 243 | + seed: &'static [u8], |
| 244 | + sk_sm: &'static [u8], |
| 245 | + } |
| 246 | + |
| 247 | + const TEST_VECTORS: &[TestVector] = &[ |
| 248 | + TestVector { |
| 249 | + dst: b"DeriveKeyPairVOPRF10-\x00\x00\x04", |
| 250 | + key_info: b"test key", |
| 251 | + seed: &hex!("a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3"), |
| 252 | + sk_sm: &hex!("c0503759ddd1e31d8c7eae9304c9b1c16f83d1f6d962e3e7b789cd85fd581800e96c5c4256131aafcff9a76919abbd55"), |
| 253 | + }, |
| 254 | + TestVector { |
| 255 | + dst: b"DeriveKeyPairVOPRF10-\x01\x00\x04", |
| 256 | + key_info: b"test key", |
| 257 | + seed: &hex!("a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3"), |
| 258 | + sk_sm: &hex!("514fb6fe2e66af1383840759d56f71730331280f062930ee2a2f7ea42f935acf94087355699d788abfdf09d19a5c85ac"), |
| 259 | + }, |
| 260 | + TestVector { |
| 261 | + dst: b"DeriveKeyPairVOPRF10-\x02\x00\x04", |
| 262 | + key_info: b"test key", |
| 263 | + seed: &hex!("a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3"), |
| 264 | + sk_sm: &hex!("0fcba4a204f67d6c13f780e613915f755319aaa3cb03cd20a5a4a6c403a4812a4fff5d3223e2c309aa66b05cb7611fd4"), |
| 265 | + }, |
| 266 | + ]; |
| 267 | + |
| 268 | + 'outer: for test_vector in TEST_VECTORS { |
| 269 | + let key_info_len = u16::try_from(test_vector.key_info.len()) |
| 270 | + .unwrap() |
| 271 | + .to_be_bytes(); |
| 272 | + |
| 273 | + for counter in 0_u8..=u8::MAX { |
| 274 | + let scalar = NistP384::hash_to_scalar::<ExpandMsgXmd<Sha384>>( |
| 275 | + &[ |
| 276 | + test_vector.seed, |
| 277 | + &key_info_len, |
| 278 | + test_vector.key_info, |
| 279 | + &counter.to_be_bytes(), |
| 280 | + ], |
| 281 | + test_vector.dst, |
| 282 | + ) |
| 283 | + .unwrap(); |
| 284 | + |
| 285 | + if !bool::from(scalar.is_zero()) { |
| 286 | + assert_eq!(scalar.to_bytes().as_slice(), test_vector.sk_sm); |
| 287 | + continue 'outer; |
| 288 | + } |
| 289 | + } |
| 290 | + |
| 291 | + panic!("deriving key failed"); |
| 292 | + } |
| 293 | + } |
| 294 | + |
| 295 | + #[test] |
| 296 | + fn from_okm_fuzz() { |
| 297 | + let mut wide_order = GenericArray::default(); |
| 298 | + wide_order[24..].copy_from_slice(&NistP384::ORDER.to_be_byte_array()); |
| 299 | + let wide_order = NonZero::new(U576::from_be_byte_array(wide_order)).unwrap(); |
| 300 | + |
| 301 | + let simple_from_okm = move |data: GenericArray<u8, U72>| -> Scalar { |
| 302 | + let data = U576::from_be_slice(&data); |
| 303 | + |
| 304 | + let scalar = data % wide_order; |
| 305 | + let reduced_scalar = U384::from_be_slice(&scalar.to_be_byte_array()[24..]); |
| 306 | + |
| 307 | + Scalar::from_uint_reduced(reduced_scalar) |
| 308 | + }; |
| 309 | + |
| 310 | + proptest!(ProptestConfig::with_cases(1000), |(b0 in ANY, b1 in ANY, b2 in ANY, b3 in ANY, b4 in ANY, b5 in ANY, b6 in ANY, b7 in ANY, b8 in ANY)| { |
| 311 | + let mut data = GenericArray::default(); |
| 312 | + data[..8].copy_from_slice(&b0.to_be_bytes()); |
| 313 | + data[8..16].copy_from_slice(&b1.to_be_bytes()); |
| 314 | + data[16..24].copy_from_slice(&b2.to_be_bytes()); |
| 315 | + data[24..32].copy_from_slice(&b3.to_be_bytes()); |
| 316 | + data[32..40].copy_from_slice(&b4.to_be_bytes()); |
| 317 | + data[40..48].copy_from_slice(&b5.to_be_bytes()); |
| 318 | + data[48..56].copy_from_slice(&b6.to_be_bytes()); |
| 319 | + data[56..64].copy_from_slice(&b7.to_be_bytes()); |
| 320 | + data[64..].copy_from_slice(&b8.to_be_bytes()); |
| 321 | + |
| 322 | + let from_okm = Scalar::from_okm(&data); |
| 323 | + let simple_from_okm = simple_from_okm(data); |
| 324 | + assert_eq!(from_okm, simple_from_okm); |
| 325 | + }); |
| 326 | + } |
| 327 | +} |
0 commit comments