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
use ffi;
use std::mem;
pub fn check(signature: [u8; 64], public_key: [u8; 32], message: &[u8]) -> Result<(), String> {
unsafe {
if ffi::crypto_check(
signature.as_ptr(),
public_key.as_ptr(),
message.as_ptr(),
message.len(),
) == 0
{
return Ok(());
}
Err("Forged message detected.".to_owned())
}
}
pub struct Context(ffi::crypto_check_ctx);
impl Context {
#[inline]
pub fn new(signature: [u8; 64], public_key: [u8; 32]) -> Context {
unsafe {
let mut ctx = mem::uninitialized();
ffi::crypto_check_init(&mut ctx, signature.as_ptr(), public_key.as_ptr());
Context(ctx)
}
}
#[inline]
pub fn update(&mut self, message: &[u8]) {
unsafe {
ffi::crypto_check_update(&mut self.0, message.as_ptr(), message.len());
}
}
#[inline]
pub fn finalize(&mut self) -> Result<(), String> {
unsafe {
if ffi::crypto_check_final(&mut self.0) == 0 {
return Ok(());
}
Err("Message corrupted, aborting.".to_owned())
}
}
}
#[cfg(test)]
mod test {
use super::*;
use ::pubkey::sign;
#[test]
fn check() {
let secret_key = [2u8; 32];
let public_key = ::pubkey::sign::public_key(secret_key);
let sig = sign::sign(secret_key, public_key, "test".as_bytes());
let ret = ::pubkey::check::check(sig, public_key, "test".as_bytes());
assert_eq!(ret.is_ok(), true)
}
#[test]
fn check_forged() {
let secret_key = [2u8; 32];
let public_key = sign::public_key(secret_key);
let sig = sign::sign(secret_key, public_key, "test".as_bytes());
let ret = ::pubkey::check::check(sig, public_key, "not_test".as_bytes());
assert_eq!(ret.is_err(), true)
}
#[test]
fn ctx() {
let secret_key = [2u8; 32];
let public_key = ::pubkey::sign::public_key(secret_key);
let sig = sign::sign(secret_key, public_key, "test".as_bytes());
let mut ctx = Context::new(sig, public_key);
ctx.update("test".as_bytes());
let ret = ctx.finalize();
assert_eq!(ret.is_ok(), true)
}
#[test]
fn ctx_fail() {
let secret_key = [2u8; 32];
let public_key = ::pubkey::sign::public_key(secret_key);
let sig = sign::sign(secret_key, public_key, "test".as_bytes());
let mut ctx = Context::new(sig, public_key);
ctx.update("not_test".as_bytes());
let ret = ctx.finalize();
assert_eq!(ret.is_err(), true);
assert_eq!(ret.err().unwrap(), "Message corrupted, aborting.".to_owned());
}
}