1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/// Constant values relevant for Ed25519
pub mod consts {
/// Private Key Size (64 bytes)
pub const ED25519_PRIVATE_KEY_BYTELEN: usize = 64;
/// Public Key Size (32 bytes)
pub const ED25519_PUBLIC_KEY_BYTELEN: usize = 32;
/// Signature Size (32 bytes)
pub const ED25519_SIGNATURE_BYTELEN: usize = 64;
}
pub mod algorithms {
unsafe extern "C" {
/// This function generates an Ed25519 keypair.
/// Parameters:
/// - pk (Public Key) <- mutable raw pointer to an array of 32 unsigned bytes
/// - sk (Private Key) <- mutable raw pointer to an array of 64 unsigned bytes
pub unsafe fn lib25519_sign_ed25519_keypair(pk: *mut u8, sk: *mut u8);
/// This function signs a message using a private key and stores the output in `sm`.
/// Parameters:
/// - sm (Signed Message) <- mutable raw pointer to an array of `smlen` unsigned bytes
/// - smlen (Signed Message Length) <- mutable reference to a signed 64-bit integer = (`mlen`` + 32)
/// - m (Message) <- raw pointer to an array of `mlen` unsigned bytes
/// - mlen (Message Length) <- a 64-bit signed integer
/// - sk (Private Key) <- raw pointer to an array of 64 unsigned bytes
pub unsafe fn lib25519_sign_ed25519(
sm: *mut u8,
smlen: *mut i64,
m: *const u8,
mlen: i64,
sk: *const u8,
);
/// This function verifies the signatures of a message using a public key.
/// Outputs `0` if a message was verified successfully and `-1`` otherwise.
/// Parameters:
/// - m (Message) <- mutable raw pointer to an array of `mlen` unsigned bytes
/// - mlen (Message Length) <- mutable reference to a signed 64-bit integer
/// - sm (Signed Message) <- raw pointer to an array of `smlen` unsigned bytes
/// - smlen (Signed Message Length) <- signed 64-bit integer = (`mlen`` + 32)
/// - pk (Public Key) <- raw pointer to an array of 32 unsigned bytes
pub unsafe fn lib25519_sign_ed25519_open(
m: *mut u8,
mlen: *mut i64,
sm: *const u8,
smlen: i64,
pk: *const u8,
) -> std::ffi::c_int;
}
}
#[cfg(test)]
mod tests {
use crate::ed25519::{
algorithms::{
lib25519_sign_ed25519, lib25519_sign_ed25519_keypair, lib25519_sign_ed25519_open,
},
consts::{
ED25519_PRIVATE_KEY_BYTELEN, ED25519_PUBLIC_KEY_BYTELEN, ED25519_SIGNATURE_BYTELEN,
},
};
use rand::prelude::*;
#[test]
fn test_end_to_end_signature_verification() {
// Set Message Length
const MLEN: usize = 1000;
// Set Signed Message Length
const SMLEN: usize = MLEN + ED25519_SIGNATURE_BYTELEN;
// Allocate Memory for Private Key
let mut sk: [u8; ED25519_PRIVATE_KEY_BYTELEN] = [0; ED25519_PRIVATE_KEY_BYTELEN];
// Allocate Memory for Public Key
let mut pk: [u8; ED25519_PUBLIC_KEY_BYTELEN] = [0; ED25519_PUBLIC_KEY_BYTELEN];
// Allocate Memory for Message
let mut msg: [u8; MLEN] = [0; MLEN];
let mut rng = rand::thread_rng();
// Fill Message with Random Bytes
rng.fill_bytes(&mut msg);
// Allocate Memory for Signed Message
let mut signed_msg: [u8; SMLEN] = [0; SMLEN];
let mut smlen: i64 = SMLEN as i64;
let mut mlen: i64 = MLEN as i64;
let verification_result;
unsafe {
// Generate Keypair
lib25519_sign_ed25519_keypair(pk.as_mut_ptr(), sk.as_mut_ptr());
// Sign Message
lib25519_sign_ed25519(
signed_msg.as_mut_ptr(),
&mut smlen,
msg.as_ptr(),
mlen,
sk.as_ptr(),
);
// Verify Signature
verification_result = lib25519_sign_ed25519_open(
msg.as_mut_ptr(),
&mut mlen,
signed_msg.as_ptr(),
smlen,
pk.as_ptr(),
)
};
// Check Verification Result
assert_eq!(verification_result, 0)
}
}