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
use super::error::Error;
use super::signature::Signature;
use super::{Message, Pubkey, SECP256K1};
use ckb_fixed_hash::H256;
use secp256k1::key;
use secp256k1::Message as SecpMessage;
use std::str::FromStr;
use std::{ptr, sync::atomic};
#[derive(Clone, Eq, PartialEq)]
pub struct Privkey {
inner: H256,
}
impl Privkey {
pub fn sign_recoverable(&self, message: &Message) -> Result<Signature, Error> {
let context = &SECP256K1;
let message = message.as_ref();
let privkey = key::SecretKey::from_slice(self.inner.as_bytes())?;
let message = SecpMessage::from_slice(message)?;
let data = context.sign_recoverable(&message, &privkey);
let (rec_id, data) = data.serialize_compact();
Ok(Signature::from_compact(rec_id, data))
}
pub fn pubkey(&self) -> Result<Pubkey, Error> {
let context = &SECP256K1;
let privkey = key::SecretKey::from_slice(self.inner.as_bytes())?;
let pubkey = key::PublicKey::from_secret_key(context, &privkey);
Ok(Pubkey::from(pubkey))
}
pub fn from_slice(key: &[u8]) -> Self {
assert_eq!(32, key.len(), "should provide 32-byte length slice");
let mut h = [0u8; 32];
h.copy_from_slice(&key[0..32]);
Privkey { inner: h.into() }
}
pub(crate) fn zeroize(&mut self) {
for elem in self.inner.0.iter_mut() {
volatile_write(elem, Default::default());
atomic_fence();
}
}
}
impl From<H256> for Privkey {
fn from(key: H256) -> Self {
Privkey { inner: key }
}
}
impl FromStr for Privkey {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(H256::from_str(s)
.map_err(|e| Error::Other(format!("{:?}", e)))?
.into())
}
}
impl From<key::SecretKey> for Privkey {
fn from(key: key::SecretKey) -> Self {
let mut h = [0u8; 32];
h.copy_from_slice(&key[0..32]);
Privkey { inner: h.into() }
}
}
#[inline]
fn atomic_fence() {
atomic::compiler_fence(atomic::Ordering::SeqCst);
}
#[inline]
fn volatile_write<T: Copy + Sized>(dst: &mut T, src: T) {
unsafe { ptr::write_volatile(dst, src) }
}
impl Drop for Privkey {
fn drop(&mut self) {
self.zeroize()
}
}