Skip to content

Commit 2c43b81

Browse files
committed
roundtrip tests for schnorr
1 parent 1ec3605 commit 2c43b81

2 files changed

Lines changed: 411 additions & 0 deletions

File tree

crates/basis_offchain/src/schnorr.rs

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,4 +261,225 @@ pub fn schnorr_verify(
261261
}
262262

263263
Ok(())
264+
}
265+
266+
#[cfg(test)]
267+
mod tests {
268+
use super::*;
269+
270+
#[test]
271+
fn test_schnorr_roundtrip() {
272+
// Generate a key pair
273+
let (secret_key, public_key) = generate_keypair();
274+
275+
// Create test data
276+
let recipient_pubkey = public_key; // Use the generated public key as recipient
277+
let amount = 1000000000u64; // 1 ERG in nanoERG
278+
let timestamp = 1672531200u64; // Example timestamp
279+
280+
// Create the message to be signed
281+
let message = signing_message(&recipient_pubkey, amount, timestamp);
282+
283+
// Sign the message
284+
let signature = schnorr_sign(&message, &secret_key, &recipient_pubkey)
285+
.expect("Signing should succeed");
286+
287+
// Verify the signature
288+
schnorr_verify(&signature, &message, &recipient_pubkey)
289+
.expect("Verification should succeed");
290+
291+
assert_eq!(signature.len(), 65, "Signature should be 65 bytes");
292+
}
293+
294+
#[test]
295+
fn test_schnorr_with_tampered_message() {
296+
// Generate a key pair
297+
let (secret_key, public_key) = generate_keypair();
298+
299+
// Create test data
300+
let recipient_pubkey = public_key; // Use the generated public key as recipient
301+
let amount = 1000000000u64; // 1 ERG in nanoERG
302+
let timestamp = 1672531200u64; // Example timestamp
303+
304+
// Create the message to be signed
305+
let message = signing_message(&recipient_pubkey, amount, timestamp);
306+
307+
// Sign the message
308+
let signature = schnorr_sign(&message, &secret_key, &recipient_pubkey)
309+
.expect("Signing should succeed");
310+
311+
// Tamper with the message
312+
let mut tampered_message = message.clone();
313+
tampered_message[0] ^= 0x01; // Flip one bit
314+
315+
// Verify with tampered message (should fail)
316+
let result = schnorr_verify(&signature, &tampered_message, &recipient_pubkey);
317+
318+
assert!(result.is_err(), "Verification should fail with tampered message");
319+
}
320+
321+
#[test]
322+
fn test_schnorr_with_wrong_public_key() {
323+
// Generate two key pairs
324+
let (secret_key1, public_key1) = generate_keypair();
325+
let (secret_key2, public_key2) = generate_keypair();
326+
327+
// Create test data
328+
let recipient_pubkey = public_key1; // Use first public key as recipient
329+
let amount = 1000000000u64; // 1 ERG in nanoERG
330+
let timestamp = 1672531200u64; // Example timestamp
331+
332+
// Create the message to be signed
333+
let message = signing_message(&recipient_pubkey, amount, timestamp);
334+
335+
// Sign the message with first party's key
336+
let signature = schnorr_sign(&message, &secret_key1, &recipient_pubkey)
337+
.expect("Signing should succeed");
338+
339+
// Verify with second party's public key (should fail)
340+
let result = schnorr_verify(&signature, &message, &public_key2);
341+
342+
assert!(result.is_err(), "Verification should fail with wrong public key");
343+
}
344+
345+
#[test]
346+
fn test_signing_message_format() {
347+
let recipient_pubkey = [0x02u8; 33]; // Example public key
348+
let amount = 1000000000u64;
349+
let timestamp = 1672531200u64;
350+
351+
let message = signing_message(&recipient_pubkey, amount, timestamp);
352+
353+
// Verify the format: recipient_pubkey (33 bytes) + amount_be_bytes (8 bytes) + timestamp_be_bytes (8 bytes)
354+
assert_eq!(message.len(), 33 + 8 + 8, "Message should be 49 bytes");
355+
assert_eq!(&message[0..33], &recipient_pubkey, "First 33 bytes should be recipient pubkey");
356+
assert_eq!(&message[33..41], &amount.to_be_bytes(), "Next 8 bytes should be amount in big endian");
357+
assert_eq!(&message[41..49], &timestamp.to_be_bytes(), "Last 8 bytes should be timestamp in big endian");
358+
}
359+
360+
#[test]
361+
fn test_invalid_signature_length() {
362+
// This test is actually testing the validation inside the function
363+
// Since the function signature requires [u8; 65], we can't pass a [u8; 64]
364+
// So instead we'll test the internal validation by creating a signature that fails validation
365+
let (_, public_key) = generate_keypair();
366+
let message = signing_message(&public_key, 1000, 1234567890);
367+
368+
// Create a signature with invalid 'a' component to trigger validation failure
369+
let mut invalid_signature = [0u8; 65];
370+
invalid_signature[0] = 0x01; // Invalid prefix (should be 0x02 or 0x03)
371+
372+
let result = schnorr_verify(&invalid_signature, &message, &public_key);
373+
assert!(result.is_err(), "Verification should fail with invalid signature format");
374+
}
375+
376+
#[test]
377+
fn test_invalid_signature_a_component() {
378+
let (_, public_key) = generate_keypair();
379+
let message = signing_message(&public_key, 1000, 1234567890);
380+
381+
// Create a signature with invalid 'a' component (not a valid compressed point)
382+
let mut invalid_signature = [0u8; 65];
383+
invalid_signature[0] = 0x01; // Invalid prefix (should be 0x02 or 0x03)
384+
385+
let result = schnorr_verify(&invalid_signature, &message, &public_key);
386+
assert!(result.is_err(), "Verification should fail with invalid 'a' component");
387+
}
388+
389+
#[test]
390+
fn test_invalid_signature_z_component_all_zeros() {
391+
let (_, public_key) = generate_keypair();
392+
let message = signing_message(&public_key, 1000, 1234567890);
393+
394+
// Create a signature with 'z' component all zeros
395+
let mut invalid_signature = [0u8; 65];
396+
invalid_signature[0] = 0x02; // Valid prefix
397+
// Leave the z component as all zeros (bytes 33-65)
398+
399+
let result = schnorr_verify(&invalid_signature, &message, &public_key);
400+
assert!(result.is_err(), "Verification should fail with all-zeros 'z' component");
401+
}
402+
403+
#[test]
404+
fn test_invalid_public_key_length() {
405+
let (secret_key, public_key) = generate_keypair();
406+
let message = signing_message(&public_key, 1000, 1234567890);
407+
408+
// Sign with valid key
409+
let signature = schnorr_sign(&message, &secret_key, &public_key)
410+
.expect("Signing should succeed");
411+
412+
// Create an invalid public key with wrong length
413+
let invalid_pubkey = [0x02u8; 32]; // 32 bytes instead of 33
414+
415+
// Need to create a proper 33-byte array to pass to the function
416+
let mut invalid_pubkey_33 = [0x02u8; 33];
417+
invalid_pubkey_33[0] = 0x01; // Invalid prefix
418+
419+
let result = schnorr_verify(&signature, &message, &invalid_pubkey_33);
420+
assert!(result.is_err(), "Verification should fail with invalid public key");
421+
}
422+
423+
#[test]
424+
fn test_invalid_public_key_prefix() {
425+
let (secret_key, public_key) = generate_keypair();
426+
let message = signing_message(&public_key, 1000, 1234567890);
427+
428+
// Sign with valid key
429+
let signature = schnorr_sign(&message, &secret_key, &public_key)
430+
.expect("Signing should succeed");
431+
432+
// Create a public key with invalid prefix
433+
let mut invalid_pubkey = public_key;
434+
invalid_pubkey[0] = 0x01; // Invalid prefix (should be 0x02 or 0x03)
435+
436+
let result = schnorr_verify(&signature, &message, &invalid_pubkey);
437+
assert!(result.is_err(), "Verification should fail with invalid public key prefix");
438+
}
439+
440+
#[test]
441+
fn test_empty_message() {
442+
let (secret_key, public_key) = generate_keypair();
443+
let empty_message: Vec<u8> = vec![];
444+
445+
let result = schnorr_sign(&empty_message, &secret_key, &public_key);
446+
// Signing with empty message should still work (the algorithm doesn't validate message content)
447+
if result.is_ok() {
448+
let signature = result.unwrap();
449+
let verify_result = schnorr_verify(&signature, &empty_message, &public_key);
450+
assert!(verify_result.is_ok(), "Verification should succeed with empty message if signing worked");
451+
}
452+
}
453+
454+
#[test]
455+
fn test_signature_with_modified_a_component() {
456+
let (secret_key, public_key) = generate_keypair();
457+
let message = signing_message(&public_key, 1000, 1234567890);
458+
459+
// Sign the message
460+
let mut signature = schnorr_sign(&message, &secret_key, &public_key)
461+
.expect("Signing should succeed");
462+
463+
// Modify the 'a' component (first 33 bytes)
464+
signature[0] ^= 0x01; // Flip a bit in the 'a' component
465+
466+
let result = schnorr_verify(&signature, &message, &public_key);
467+
assert!(result.is_err(), "Verification should fail when 'a' component is modified");
468+
}
469+
470+
#[test]
471+
fn test_signature_with_modified_z_component() {
472+
let (secret_key, public_key) = generate_keypair();
473+
let message = signing_message(&public_key, 1000, 1234567890);
474+
475+
// Sign the message
476+
let mut signature = schnorr_sign(&message, &secret_key, &public_key)
477+
.expect("Signing should succeed");
478+
479+
// Modify the 'z' component (bytes 33-65)
480+
signature[33] ^= 0x01; // Flip a bit in the 'z' component
481+
482+
let result = schnorr_verify(&signature, &message, &public_key);
483+
assert!(result.is_err(), "Verification should fail when 'z' component is modified");
484+
}
264485
}

0 commit comments

Comments
 (0)