1use bls12_381::*;
2use group::Curve;
3
4use blst::BLST_ERROR;
6use blst::min_pk::{PublicKey as BlsPublicKey, SecretKey as BlsSecretKey, Signature as BlsSignature};
7
8use crate::types::{PublicKey, Signature};
9
10#[derive(Debug, thiserror::Error)]
11pub enum Error {
12 #[error("invalid secret key")]
13 InvalidSecretKey,
14 #[error("invalid point")]
15 InvalidPoint,
16 #[error("invalid signature")]
17 InvalidSignature,
18 #[error("verification failed")]
19 VerificationFailed,
20 #[error("zero-sized input")]
21 ZeroSizedInput,
22}
23
24fn parse_secret_key(sk_bytes: &[u8]) -> Result<BlsSecretKey, Error> {
26 if let Ok(bytes_64) = <&[u8; 64]>::try_from(sk_bytes) {
31 let sk_scalar = Scalar::from_bytes_wide(bytes_64);
32 let mut sk_be = sk_scalar.to_bytes();
33 sk_be.reverse(); return BlsSecretKey::from_bytes(&sk_be).map_err(|_| Error::InvalidSecretKey);
36 }
37 Err(Error::InvalidSecretKey)
38}
39
40fn g1_projective_is_valid(projective: &G1Projective) -> bool {
41 let is_identity: bool = projective.is_identity().into();
42 let is_on_curve = projective.is_on_curve().into();
43 let is_torsion_free = projective.to_affine().is_torsion_free().into();
44 !is_identity && is_on_curve && is_torsion_free
45}
46
47fn g2_affine_is_valid(affine: &G2Affine) -> bool {
48 let is_identity: bool = affine.is_identity().into();
49 let is_on_curve = affine.is_on_curve().into();
50 let is_torsion_free = affine.is_torsion_free().into();
51 !is_identity && is_on_curve && is_torsion_free
52}
53
54fn parse_public_key(bytes: &[u8]) -> Result<G1Projective, Error> {
55 if bytes.len() != 48 {
56 return Err(Error::InvalidPoint);
57 }
58 let mut res = [0u8; 48];
59 res.copy_from_slice(bytes);
60
61 match Option::<G1Affine>::from(G1Affine::from_compressed(&res)) {
62 Some(affine) => {
63 let projective = G1Projective::from(affine);
64 if g1_projective_is_valid(&projective) { Ok(projective) } else { Err(Error::InvalidPoint) }
65 }
66 None => Err(Error::InvalidPoint),
67 }
68}
69
70fn parse_signature(bytes: &[u8]) -> Result<G2Projective, Error> {
71 if bytes.len() != 96 {
72 return Err(Error::InvalidPoint);
73 }
74 let mut res = [0u8; 96];
75 res.copy_from_slice(bytes);
76
77 match Option::from(G2Affine::from_compressed(&res)) {
78 Some(affine) => {
79 if g2_affine_is_valid(&affine) {
80 Ok(G2Projective::from(affine))
81 } else {
82 Err(Error::InvalidPoint)
83 }
84 }
85 None => Err(Error::InvalidPoint),
86 }
87}
88
89fn sign_from_secret_key(sk: BlsSecretKey, msg: &[u8], dst: &[u8]) -> Result<BlsSignature, Error> {
90 Ok(sk.sign(msg, dst, &[]))
91}
92
93pub fn get_public_key(sk_bytes: &[u8]) -> Result<PublicKey, Error> {
97 let bytes_64: [u8; 64] = sk_bytes.try_into().map_err(|_| Error::InvalidSecretKey)?;
99 let sk_scalar = Scalar::from_bytes_wide(&bytes_64);
100
101 let pk_g1 = G1Projective::generator() * sk_scalar;
103 Ok(PublicKey::from(pk_g1.to_affine().to_compressed()))
104}
105
106pub fn generate_sk() -> [u8; 64] {
107 loop {
109 let sk_64: [u8; 64] = rand::random();
110
111 let scalar = Scalar::from_bytes_wide(&sk_64);
113 let scalar_bytes = scalar.to_bytes();
114
115 if BlsSecretKey::from_bytes(&scalar_bytes).is_ok() {
117 return sk_64;
118 }
119
120 }
122}
123
124pub fn sign(sk_bytes: &[u8], message: &[u8], dst: &[u8]) -> Result<Signature, Error> {
127 let sk = parse_secret_key(sk_bytes)?;
129 let signature = sign_from_secret_key(sk, message, dst)?;
130 Ok(Signature::from(signature.to_bytes()))
131}
132
133pub fn verify(pk_bytes: impl AsRef<[u8]>, sig_bytes: impl AsRef<[u8]>, msg: &[u8], dst: &[u8]) -> Result<(), Error> {
136 let pk = BlsPublicKey::deserialize(pk_bytes.as_ref()).map_err(|_| Error::InvalidPoint)?;
137 let sig = BlsSignature::deserialize(sig_bytes.as_ref()).map_err(|_| Error::InvalidSignature)?;
138
139 let err = sig.verify(
140 true, msg,
142 dst, &[], &pk,
145 true, );
147
148 if err == BLST_ERROR::BLST_SUCCESS { Ok(()) } else { Err(Error::VerificationFailed) }
149}
150
151pub fn aggregate_public_keys<T>(public_keys: T) -> Result<PublicKey, Error>
153where
154 T: IntoIterator,
155 T::Item: AsRef<[u8]>,
156{
157 let mut iter = public_keys.into_iter();
158 let first = match iter.next() {
159 Some(v) => v,
160 None => return Err(Error::ZeroSizedInput),
161 };
162 let mut acc = parse_public_key(first.as_ref())?;
163 for pk in iter {
164 let p = parse_public_key(pk.as_ref())?;
165 acc += p;
166 }
167 Ok(PublicKey::from(acc.to_affine().to_compressed()))
168}
169
170pub fn aggregate_signatures<T>(signatures: T) -> Result<Signature, Error>
172where
173 T: IntoIterator,
174 T::Item: AsRef<[u8]>,
175{
176 let mut iter = signatures.into_iter();
177 let first = match iter.next() {
178 Some(v) => v,
179 None => return Err(Error::ZeroSizedInput),
180 };
181 let mut acc = parse_signature(first.as_ref())?;
182 for s in iter {
183 let p = parse_signature(s.as_ref())?;
184 acc += p;
185 }
186 Ok(Signature::from(acc.to_affine().to_compressed()))
187}
188
189pub fn get_shared_secret(public_key: impl AsRef<[u8]>, sk_bytes: &[u8]) -> Result<PublicKey, Error> {
192 let pk_g1 = parse_public_key(public_key.as_ref())?;
193
194 let sk_scalar = if sk_bytes.len() == 64 {
196 let bytes_64: [u8; 64] = sk_bytes.try_into().map_err(|_| Error::InvalidSecretKey)?;
198 Scalar::from_bytes_wide(&bytes_64)
199 } else {
200 return Err(Error::InvalidSecretKey);
201 };
202
203 Ok(PublicKey::from((pk_g1 * sk_scalar).to_affine().to_compressed()))
205}
206
207pub fn validate_public_key(public_key: impl AsRef<[u8]>) -> Result<(), Error> {
209 parse_public_key(public_key.as_ref()).map(|_| ())
210}
211
212#[cfg(test)]
213mod tests {
214 use super::*;
215
216 #[allow(dead_code)]
217 fn seed32(b: u8) -> [u8; 32] {
218 [b; 32]
219 }
220
221 #[test]
222 fn pk_sign_verify_and_validate() {
223 let seed = generate_sk();
224 let pk = get_public_key(&seed).expect("pk");
225 validate_public_key(&pk).expect("valid pk");
226
227 let msg = b"context7:message";
228 let dst = b"CONTEXT7-BLS-DST";
229 let sig = sign(&seed, msg, dst).expect("sign");
230 verify(&pk, &sig, msg, dst).expect("verify");
231 }
232
233 #[test]
234 fn shared_secret_symmetry() {
235 let a = generate_sk();
236 let b = generate_sk();
237 let pk_a = get_public_key(&a).unwrap();
238 let pk_b = get_public_key(&b).unwrap();
239 let ab = get_shared_secret(&pk_b, &a).unwrap();
240 let ba = get_shared_secret(&pk_a, &b).unwrap();
241 assert_eq!(ab, ba);
242 }
243
244 #[test]
245 fn shared_secret_symmetry_64byte() {
246 let sk_a = generate_sk();
248 let sk_b = generate_sk();
249
250 let pk_a = get_public_key(&sk_a).unwrap();
251 let pk_b = get_public_key(&sk_b).unwrap();
252
253 let sk_a_scalar = Scalar::from_bytes_wide(&sk_a);
255 let sk_b_scalar = Scalar::from_bytes_wide(&sk_b);
256 let sk_a_blst_valid = BlsSecretKey::from_bytes(&sk_a_scalar.to_bytes()).is_ok();
257 let sk_b_blst_valid = BlsSecretKey::from_bytes(&sk_b_scalar.to_bytes()).is_ok();
258
259 println!("sk_a BLST valid: {}", sk_a_blst_valid);
260 println!("sk_b BLST valid: {}", sk_b_blst_valid);
261
262 let ab = get_shared_secret(&pk_b, &sk_a).unwrap();
263 let ba = get_shared_secret(&pk_a, &sk_b).unwrap();
264
265 println!("AB: {:?}", &ab[..8]);
266 println!("BA: {:?}", &ba[..8]);
267
268 assert_eq!(ab, ba, "64-byte shared secrets should be symmetric");
269 }
270
271 #[test]
272 fn aggregation_behaviour() {
273 let s1 = generate_sk();
274 let s2 = generate_sk();
275 let pk1 = get_public_key(&s1).unwrap();
276 let pk2 = get_public_key(&s2).unwrap();
277
278 let agg1 = aggregate_public_keys([pk1]).unwrap();
280 assert_eq!(agg1.len(), 48);
281 assert_eq!(agg1, pk1); let agg_pk = aggregate_public_keys([pk1, pk2]).unwrap();
285 assert_eq!(agg_pk.len(), 48);
286 assert_ne!(agg_pk, pk1); assert_ne!(agg_pk, pk2);
288
289 assert!(matches!(aggregate_public_keys::<[&[u8]; 0]>([]), Err(Error::ZeroSizedInput)));
291
292 let dst = b"DST";
294 let msg = b"m";
295 let sig1 = sign(&s1, msg, dst).unwrap();
296 let sig2 = sign(&s2, msg, dst).unwrap();
297
298 let agg_sig1 = aggregate_signatures([sig1.as_slice()]).unwrap();
300 assert_eq!(agg_sig1.len(), 96);
301 assert_eq!(agg_sig1, sig1); let agg_sig = aggregate_signatures([sig1.as_slice(), sig2.as_slice()]).unwrap();
305 assert_eq!(agg_sig.len(), 96);
306 assert_ne!(agg_sig, sig1); assert_ne!(agg_sig, sig2);
308
309 assert!(matches!(aggregate_signatures::<[&[u8]; 0]>([]), Err(Error::ZeroSizedInput)));
311
312 verify(&agg_pk, &agg_sig, msg, dst).expect("aggregated signature should verify against aggregated public key");
314
315 assert!(verify(&agg_pk, &sig1, msg, dst).is_err());
317 assert!(verify(&agg_pk, &sig2, msg, dst).is_err());
318
319 assert!(verify(&pk1, &agg_sig, msg, dst).is_err());
321 assert!(verify(&pk2, &agg_sig, msg, dst).is_err());
322 }
323
324 #[test]
325 fn elixir_key_compatibility_test() {
326 const SK_B58: &str = "QPHHRpzuJ8nBKnrY9hcT8DuaWX8ev42QWHMPtpWtg11Rkbq37cpE5BGD8RTBe6NrfQqboKusvz119rUMDjoMXQ2";
327 const PK_B58: &str = "7HBdTuiVETYS9bWgZt2ZQ2edrmUYVW9gMPJuVRA2PEFXUvTt62ZxP1juPbHpUS8M1k";
328 const OTHER_PK_B58: &str = "7KUntjPCFEmTtG9NBLNjqaaXourYDjBASwLtXFcPr1DmDNPCLVKRznppysMMyAcVa7";
329 const EXPECTED_SIG_B58: &str = "nDmcy3orsbusmMA9ugTXYyCXuCpdeuar5TonQqZquGbfLGGpCkawaStX9vCxm4nnjF9CXtwVUxjbvyU5KRP6nd24niXu7oLRhvGkkiSqgnxenAgjnUJwvahfDz94t7LyBmY";
330 const EXPECTED_SHARED_SECRET_B58: &str = "69m86NjrftmWr8in6dbDBYiYrsiJjeKAvkM8WzLWk4Feub5p3YC2oDa8FbSyhS3f9d";
331
332 if SK_B58.contains("PASTE_") {
334 println!("Skipping test - replace values from iex commands first");
335 return;
336 }
337
338 println!("\n=== ELIXIR KEY COMPATIBILITY TEST ===");
339
340 let sk_bytes = bs58::decode(SK_B58).into_vec().expect("decode sk");
342 let expected_pk = bs58::decode(PK_B58).into_vec().expect("decode pk");
343 let other_pk = bs58::decode(OTHER_PK_B58).into_vec().expect("decode other pk");
344 let expected_sig = bs58::decode(EXPECTED_SIG_B58).into_vec().expect("decode sig");
345 let expected_shared_secret = bs58::decode(EXPECTED_SHARED_SECRET_B58).into_vec().expect("decode shared secret");
346
347 println!("SK length: {}", sk_bytes.len());
348 println!("Expected PK length: {}", expected_pk.len());
349 println!("SK first 8 bytes: {:?}", &sk_bytes[..8]);
350 println!("SK last 8 bytes: {:?}", &sk_bytes[sk_bytes.len() - 8..]);
351
352 println!("\n--- Test 1: Secret Key Parsing ---");
354 let sk_64: [u8; 64] = sk_bytes.try_into().expect("sk should be 64 bytes");
355 match get_public_key(&sk_64) {
356 Ok(rust_pk) => {
357 println!("✓ Rust successfully parsed Elixir secret key");
358 println!("Rust PK: {:?}", rust_pk.to_vec());
359 println!("Elixir PK: {:?}", expected_pk);
360
361 if rust_pk.to_vec() == expected_pk {
362 println!("✓ Public keys match perfectly!");
363 } else {
364 panic!("✗ Public key mismatch - different BLS implementations");
365 }
366 }
367 Err(e) => {
368 panic!("✗ Rust failed to parse Elixir secret key: {:?}", e);
369 }
370 }
371
372 println!("\n--- Test 2: Signature Compatibility ---");
374 let test_data = b"Hello Amadeus Blockchain!";
375 let dst = b"AMADEUS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_TEST_";
376
377 match sign(&sk_64, test_data, dst) {
378 Ok(rust_sig) => {
379 println!("✓ Rust signature generation successful");
380 println!("Rust signature: {:?}", rust_sig.to_vec());
381 println!("Elixir signature: {:?}", expected_sig);
382
383 if rust_sig.to_vec() == expected_sig {
384 println!("✓ Signatures match perfectly!");
385 } else {
386 println!("~ Signatures differ (expected with different hash-to-curve)");
387 }
388
389 if verify(&expected_pk, &rust_sig, test_data, dst).is_ok() {
391 println!("✓ Rust signature verifies with Elixir public key");
392 } else {
393 panic!("✗ Rust signature doesn't verify with Elixir public key");
394 }
395
396 if expected_sig.len() == 96 {
398 let elixir_sig: [u8; 96] = expected_sig.try_into().unwrap();
399 if verify(&expected_pk, &elixir_sig, test_data, dst).is_ok() {
400 println!("✓ Elixir signature verifies in Rust");
401 } else {
402 panic!("✗ Elixir signature doesn't verify in Rust");
403 }
404 }
405 }
406 Err(e) => {
407 panic!("✗ Rust signature generation failed: {:?}", e);
408 }
409 }
410
411 println!("\n--- Test 3: Shared Secret Compatibility ---");
413 match get_shared_secret(&other_pk, &sk_64) {
414 Ok(rust_shared_secret) => {
415 println!("✓ Rust shared secret generation successful");
416 println!("Rust shared secret: {:?}", rust_shared_secret.to_vec());
417 println!("Elixir shared secret: {:?}", expected_shared_secret);
418
419 if rust_shared_secret.to_vec() == expected_shared_secret {
420 println!("✓ Shared secrets match perfectly!");
421 } else {
422 panic!("✗ Shared secret mismatch");
423 }
424 }
425 Err(e) => {
426 println!("✗ Rust shared secret generation failed: {:?}", e);
427 }
428 }
429
430 println!("\n=== COMPATIBILITY TEST COMPLETE ===");
431 }
432
433 #[test]
434 fn elixir_signature_compatibility_test() {
435 const SK_B58: &str = "559mzNeU7itDyHs2yUzZurTvoaLHi3nJeGjCQSi44PwcJzdqBVymRdh9G25Hg6u9pi59avrqcPpeq6DBQQVEqPxV";
436 const PK_B58: &str = "7gX58gLTX7WUGUq3PQTNYcbwfH18b3SeRTgfJ6mM5badEvbhjRXxNEBYSyfH6RjnoP";
437 const TEST_DATA_1_B58: &str = "89YouX2vBz5FKYQZueX6744sBPHjZ8AgFAmN1ySS61KebyrhdkcUk5jY2vqsqgZ8XatbkL";
438 const ELIXIR_SIG_1_B58: &str = "riqRrRupu5KuaimWbSjS8NKfV8eMYTVKt5xhTkKo9FVDzP7kKhQLmT2VJu15r9GDbkZTk1N78uMGYa6yG7NzboEHet7Xv9wtf7cn86is5GH2PzvH95Kt8RbtqC9iRr13fAZ";
439 const TEST_DATA_2_B58: &str =
440 "2moGA7MbJet3qHLaSA9kN9eFy5fTr7TdHqJGoaq5hEbt5kGEVnFxCKkC8kNE2nfrnhWtVTtaVoUWeP1GEmKs";
441 const ELIXIR_SIG_2_B58: &str = "oGRbCRrCwMVKXqHebyDsF2JTMcWghbkrHszG6oU4t4FGGp351p5L5ud7XFhrhDixVS38NWgUdmr4qprsoCe1SPq8q8FKkfGLFPjPzb6BH8Lhk3zKjWoDjmCJqUp66rwEp4c";
442
443 if SK_B58.contains("PLACEHOLDER_") {
445 println!("Skipping test - replace values from iex commands first");
446 return;
447 }
448
449 println!("\n=== ELIXIR SIGNATURE COMPATIBILITY TEST ===");
450
451 let sk_bytes = bs58::decode(SK_B58).into_vec().expect("decode sk");
453 let expected_pk = bs58::decode(PK_B58).into_vec().expect("decode pk");
454 let test_data_1 = bs58::decode(TEST_DATA_1_B58).into_vec().expect("decode test data 1");
455 let elixir_sig_1 = bs58::decode(ELIXIR_SIG_1_B58).into_vec().expect("decode elixir sig 1");
456 let test_data_2 = bs58::decode(TEST_DATA_2_B58).into_vec().expect("decode test data 2");
457 let elixir_sig_2 = bs58::decode(ELIXIR_SIG_2_B58).into_vec().expect("decode elixir sig 2");
458
459 let dst = b"AMADEUS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_ANRCHALLENGE_";
460
461 println!("SK length: {}", sk_bytes.len());
462 println!("Expected PK length: {}", expected_pk.len());
463
464 println!("\n--- Test 1: Public Key Compatibility ---");
466 let rust_pk = get_public_key(&sk_bytes).expect("get public key");
467 println!("Rust PK: {:?}", rust_pk.to_vec());
468 println!("Elixir PK: {:?}", expected_pk);
469
470 if rust_pk.to_vec() == expected_pk {
471 println!("✓ Public keys match perfectly!");
472 } else {
473 panic!("✗ Public key mismatch");
474 }
475
476 println!("\n--- Test 2: Signature Verification - Case 1 ---");
478 println!("Test data 1: {:?}", test_data_1);
479 println!("Elixir signature 1: {:?}", elixir_sig_1);
480
481 let rust_sig_1 = sign(&sk_bytes, &test_data_1, dst).expect("rust sign 1");
483 println!("Rust signature 1: {:?}", rust_sig_1.to_vec());
484
485 match verify(&expected_pk, &rust_sig_1, &test_data_1, dst) {
487 Ok(_) => println!("✓ Rust signature 1 verifies"),
488 Err(e) => panic!("✗ Rust signature 1 verification failed: {:?}", e),
489 }
490
491 if elixir_sig_1.len() == 96 {
493 let elixir_sig_1_array: [u8; 96] = elixir_sig_1.try_into().unwrap();
494 match verify(&expected_pk, &elixir_sig_1_array, &test_data_1, dst) {
495 Ok(_) => println!("✓ Elixir signature 1 verifies in Rust"),
496 Err(e) => panic!("✗ Elixir signature 1 verification failed: {:?}", e),
497 }
498 }
499
500 println!("\n--- Test 3: Signature Verification - Case 2 ---");
502 println!("Test data 2: {:?}", test_data_2);
503 println!("Elixir signature 2: {:?}", elixir_sig_2);
504
505 let rust_sig_2 = sign(&sk_bytes, &test_data_2, dst).expect("rust sign 2");
507 println!("Rust signature 2: {:?}", rust_sig_2.to_vec());
508
509 match verify(&expected_pk, &rust_sig_2, &test_data_2, dst) {
511 Ok(_) => println!("✓ Rust signature 2 verifies"),
512 Err(e) => panic!("✗ Rust signature 2 verification failed: {:?}", e),
513 }
514
515 if elixir_sig_2.len() == 96 {
517 let elixir_sig_2_array: [u8; 96] = elixir_sig_2.try_into().unwrap();
518 match verify(&expected_pk, &elixir_sig_2_array, &test_data_2, dst) {
519 Ok(_) => println!("✓ Elixir signature 2 verifies in Rust"),
520 Err(e) => panic!("✗ Elixir signature 2 verification failed: {:?}", e),
521 }
522 }
523
524 println!("\n=== SIGNATURE COMPATIBILITY TEST COMPLETE ===");
525 }
526
527 #[test]
528 fn elixir_public_key_signature_verification() {
529 let elixir_pk = vec![
531 169, 61, 121, 32, 15, 191, 174, 241, 143, 231, 124, 53, 186, 69, 28, 212, 233, 130, 22, 18, 34, 244, 13,
532 106, 212, 255, 255, 47, 184, 178, 49, 111, 90, 90, 184, 84, 230, 115, 5, 143, 205, 208, 136, 138, 2, 252,
533 27, 222,
534 ];
535
536 let test_cases = vec![
538 (
539 vec![
541 169, 61, 121, 32, 15, 191, 174, 241, 143, 231, 124, 53, 186, 69, 28, 212, 233, 130, 22, 18, 34,
542 244, 13, 106, 212, 255, 255, 47, 184, 178, 49, 111, 90, 90, 184, 84, 230, 115, 5, 143, 205, 208,
543 136, 138, 2, 252, 27, 222, 49,
544 ],
545 vec![
547 166, 193, 20, 132, 125, 87, 40, 182, 101, 225, 125, 220, 97, 93, 13, 2, 89, 220, 166, 6, 106, 203,
548 96, 63, 122, 16, 226, 117, 143, 219, 5, 105, 180, 229, 65, 58, 238, 93, 230, 253, 208, 110, 35,
549 219, 222, 176, 82, 112, 15, 149, 72, 148, 54, 88, 2, 94, 219, 26, 235, 98, 77, 202, 1, 83, 6, 38,
550 39, 150, 236, 176, 141, 222, 93, 133, 66, 154, 226, 55, 214, 100, 183, 179, 167, 140, 140, 77, 117,
551 11, 167, 219, 140, 144, 144, 160, 143, 128,
552 ],
553 ),
554 (
555 vec![
557 169, 61, 121, 32, 15, 191, 174, 241, 143, 231, 124, 53, 186, 69, 28, 212, 233, 130, 22, 18, 34,
558 244, 13, 106, 212, 255, 255, 47, 184, 178, 49, 111, 90, 90, 184, 84, 230, 115, 5, 143, 205, 208,
559 136, 138, 2, 252, 27, 222, 50, 53, 53,
560 ],
561 vec![
563 141, 6, 181, 106, 49, 117, 193, 12, 249, 102, 71, 237, 125, 55, 25, 3, 14, 199, 113, 157, 49, 168,
564 205, 89, 106, 76, 3, 37, 170, 124, 149, 45, 234, 206, 44, 177, 90, 0, 14, 111, 30, 9, 197, 189,
565 201, 43, 86, 139, 22, 145, 182, 32, 77, 220, 35, 186, 5, 251, 37, 173, 187, 243, 110, 33, 57, 23,
566 67, 58, 166, 74, 200, 145, 232, 5, 151, 244, 62, 216, 159, 43, 131, 43, 179, 105, 154, 33, 91, 88,
567 143, 91, 40, 147, 129, 228, 37, 98,
568 ],
569 ),
570 (
571 vec![
573 169, 61, 121, 32, 15, 191, 174, 241, 143, 231, 124, 53, 186, 69, 28, 212, 233, 130, 22, 18, 34,
574 244, 13, 106, 212, 255, 255, 47, 184, 178, 49, 111, 90, 90, 184, 84, 230, 115, 5, 143, 205, 208,
575 136, 138, 2, 252, 27, 222, 49, 54, 52, 48, 57, 57, 53, 50, 48, 48,
576 ],
577 vec![
579 137, 145, 8, 245, 3, 166, 187, 110, 172, 28, 115, 177, 226, 179, 239, 201, 245, 173, 213, 25, 211,
580 84, 225, 194, 82, 30, 133, 105, 197, 97, 55, 185, 157, 83, 140, 89, 2, 3, 57, 7, 84, 242, 51, 161,
581 247, 238, 16, 126, 18, 69, 208, 108, 184, 132, 63, 67, 219, 144, 108, 54, 50, 176, 128, 138, 121,
582 191, 181, 168, 198, 229, 76, 246, 29, 36, 130, 95, 146, 213, 222, 230, 192, 179, 179, 198, 99, 209,
583 120, 134, 194, 181, 239, 187, 42, 46, 136, 93,
584 ],
585 ),
586 ];
587
588 let dst = b"AMADEUS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_ANRCHALLENGE_";
590
591 println!("Testing Elixir signatures with Elixir public key");
592 println!("Elixir public key: {:?}", elixir_pk);
593
594 for (i, (data, elixir_sig)) in test_cases.iter().enumerate() {
595 println!("\nTesting case {}: data_len={}, sig_len={}", i, data.len(), elixir_sig.len());
596
597 match verify(&elixir_pk, elixir_sig, data, dst) {
599 Ok(_) => println!("Case {}: ✓ Elixir signature verifies with Elixir public key", i),
600 Err(e) => {
601 println!("Case {}: ✗ Elixir signature failed verification: {:?}", i, e);
602 println!("Case {}: This indicates potential issues with Elixir test data or DST mismatch", i);
603 }
604 }
605 }
606
607 println!("\nTest completed: Checked if Elixir signatures verify with Elixir public key");
608 }
609}