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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
use super::{Error, Public, Secret, SECP256K1};
use ethereum_types::{BigEndianHash as _, H256, U256};
use lazy_static::lazy_static;
use secp256k1::constants::CURVE_ORDER as SECP256K1_CURVE_ORDER;
use secp256k1::key;
pub const BASE_POINT_BYTES: [u8; 65] = [
0x4,
0x79, 0xbe, 0x66, 0x7e, 0xf9, 0xdc, 0xbb, 0xac, 0x55, 0xa0, 0x62, 0x95, 0xce, 0x87, 0x0b, 0x07, 0x02, 0x9b, 0xfc,
0xdb, 0x2d, 0xce, 0x28, 0xd9, 0x59, 0xf2, 0x81, 0x5b, 0x16, 0xf8, 0x17, 0x98,
0x48, 0x3a, 0xda, 0x77, 0x26, 0xa3, 0xc4, 0x65, 0x5d, 0xa4, 0xfb, 0xfc, 0x0e, 0x11, 0x08, 0xa8, 0xfd, 0x17, 0xb4,
0x48, 0xa6, 0x85, 0x54, 0x19, 0x9c, 0x47, 0xd0, 0x8f, 0xfb, 0x10, 0xd4, 0xb8,
];
lazy_static! {
pub static ref CURVE_ORDER: U256 = H256::from_slice(&SECP256K1_CURVE_ORDER).into_uint();
}
pub fn public_mul_secret(public: &mut Public, secret: &Secret) -> Result<(), Error> {
let key_secret = secret.to_secp256k1_secret()?;
let mut key_public = to_secp256k1_public(public)?;
key_public.mul_assign(&SECP256K1, &key_secret[..])?;
set_public(public, &key_public);
Ok(())
}
pub fn public_add(public: &mut Public, other: &Public) -> Result<(), Error> {
let key_public = to_secp256k1_public(public)?;
let other_public = to_secp256k1_public(other)?;
let key_public = key_public.combine(&other_public)?;
set_public(public, &key_public);
Ok(())
}
pub fn public_sub(public: &mut Public, other: &Public) -> Result<(), Error> {
let mut key_neg_other = to_secp256k1_public(other)?;
key_neg_other.mul_assign(&SECP256K1, super::MINUS_ONE_KEY)?;
let mut key_public = to_secp256k1_public(public)?;
key_public = key_public.combine(&key_neg_other)?;
set_public(public, &key_public);
Ok(())
}
pub fn public_negate(public: &mut Public) -> Result<(), Error> {
let mut key_public = to_secp256k1_public(public)?;
key_public.mul_assign(&SECP256K1, super::MINUS_ONE_KEY)?;
set_public(public, &key_public);
Ok(())
}
pub fn generation_point() -> Public {
let public_key = key::PublicKey::from_slice(&BASE_POINT_BYTES).expect("constructed using constants; qed");
let mut public = Public::default();
set_public(&mut public, &public_key);
public
}
fn to_secp256k1_public(public: &Public) -> Result<key::PublicKey, Error> {
let public_data = {
let mut temp = [4u8; 65];
(&mut temp[1..65]).copy_from_slice(&public[0..64]);
temp
};
Ok(key::PublicKey::from_slice(&public_data)?)
}
fn set_public(public: &mut Public, key_public: &key::PublicKey) {
let key_public_serialized = key_public.serialize_uncompressed();
public.as_bytes_mut().copy_from_slice(&key_public_serialized[1..65]);
}
#[cfg(test)]
mod tests {
use super::super::{Generator, Random, Secret};
use super::{generation_point, public_add, public_mul_secret, public_negate, public_sub};
#[test]
fn public_addition_is_commutative() {
let public1 = Random.generate().public().clone();
let public2 = Random.generate().public().clone();
let mut left = public1.clone();
public_add(&mut left, &public2).unwrap();
let mut right = public2.clone();
public_add(&mut right, &public1).unwrap();
assert_eq!(left, right);
}
#[test]
fn public_addition_is_reversible_with_subtraction() {
let public1 = Random.generate().public().clone();
let public2 = Random.generate().public().clone();
let mut sum = public1.clone();
public_add(&mut sum, &public2).unwrap();
public_sub(&mut sum, &public2).unwrap();
assert_eq!(sum, public1);
}
#[test]
fn public_negation_is_involutory() {
let public = Random.generate().public().clone();
let mut negation = public.clone();
public_negate(&mut negation).unwrap();
public_negate(&mut negation).unwrap();
assert_eq!(negation, public);
}
#[test]
fn generation_point_expected() {
let point = generation_point();
assert_eq!(format!("{:x}", point), "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8");
}
#[test]
fn public_multiplication_verification() {
let secret =
Secret::copy_from_str(&"a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65").unwrap();
let mut public = generation_point();
public_mul_secret(&mut public, &secret).unwrap();
assert_eq!(format!("{:x}", public), "8ce0db0b0359ffc5866ba61903cc2518c3675ef2cf380a7e54bde7ea20e6fa1ab45b7617346cd11b7610001ee6ae5b0155c41cad9527cbcdff44ec67848943a4");
}
}