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
use crate::elem::{
elem_mul, elem_reduced_to_scalar, elem_to_unencoded, point_x, point_z, scalar_add, scalar_sub,
scalar_to_elem, twin_mul, Elem, Scalar, Unencoded,
};
use crate::err::KeyRejected;
use crate::jacobian::exchange::verify_jacobian_point_is_on_the_curve;
use crate::key::public::PublicKey;
use crate::limb::{Limb, LIMB_BYTES, LIMB_LENGTH};
use crate::norop::{big_endian_from_limbs, parse_big_endian};
use std::marker::PhantomData;
pub struct Signature {
r: Scalar,
s: Scalar,
}
impl Signature {
pub fn new(r: &[u8], s: &[u8]) -> Result<Self, KeyRejected> {
let mut rl = [0; LIMB_LENGTH];
parse_big_endian(&mut rl, r)?;
let r = Scalar {
limbs: rl,
m: PhantomData,
};
let mut sl = [0; LIMB_LENGTH];
parse_big_endian(&mut sl, s)?;
let s = Scalar {
limbs: sl,
m: PhantomData,
};
Ok(Signature { r, s })
}
pub fn from_scalars(r: Scalar, s: Scalar) -> Self {
Signature { r, s }
}
pub fn r(&self) -> [u8; LIMB_LENGTH * LIMB_BYTES] {
let mut r_out = [0; LIMB_LENGTH * LIMB_BYTES];
big_endian_from_limbs(&self.r.limbs, &mut r_out);
r_out
}
pub fn s(&self) -> [u8; LIMB_LENGTH * LIMB_BYTES] {
let mut s_out = [0; LIMB_LENGTH * LIMB_BYTES];
big_endian_from_limbs(&self.s.limbs, &mut s_out);
s_out
}
pub fn verify(&self, pk: &PublicKey, msg: &[u8]) -> Result<(), KeyRejected> {
let ctx = libsm::sm2::signature::SigCtx::new();
let pk_point = ctx
.load_pubkey(pk.bytes_less_safe())
.map_err(|_| KeyRejected::verify_error())?;
let digest = ctx.hash("1234567812345678", &pk_point, msg);
self.verify_digest(pk, &digest)
}
pub fn verify_digest(&self, pk: &PublicKey, digest: &[u8]) -> Result<(), KeyRejected> {
let mut dl = [0; LIMB_LENGTH];
parse_big_endian(&mut dl, digest)?;
let edl = Elem {
limbs: dl,
m: PhantomData,
};
let e = elem_reduced_to_scalar(&edl);
let (u1, u2) = (&self.s, scalar_add(&self.r, &self.s));
let r = scalar_sub(&self.r, &e);
let point = twin_mul(&u1, &u2, &pk);
verify_jacobian_point_is_on_the_curve(&point)?;
fn sig_r_equals_x(r: &Elem<Unencoded>, point: &[Limb; LIMB_LENGTH * 3]) -> bool {
let x = point_x(point);
let z = point_z(&point);
let z2 = elem_mul(&z, &z);
let r_jacobian = elem_mul(&z2, &r);
let x = elem_to_unencoded(&x);
r_jacobian.is_equal(&x)
}
let r = scalar_to_elem(&r);
if sig_r_equals_x(&r, &point) {
return Ok(());
}
Err(KeyRejected::verify_digest_error())
}
}