Skip to content

Commit

Permalink
Make signing process generate k according to RFC6979
Browse files Browse the repository at this point in the history
  • Loading branch information
rantan committed Feb 19, 2020
1 parent 1eee3ec commit 0fdf7b0
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 2 deletions.
33 changes: 31 additions & 2 deletions src/util/key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,11 @@ use std::str::FromStr;

use consensus::{encode, Decodable, Encodable};
use network::constants::Network;
use secp256k1::{self, Secp256k1};
use secp256k1::{self, Secp256k1, SecretKey};
use util::base58;
use util::signature::Signature;
use util::prime::jacobi;
use util::rfc7969::nonce_rfc6979;

/// A key-related error.
#[derive(Debug)]
Expand All @@ -39,6 +40,8 @@ pub enum Error {
Base58(base58::Error),
/// secp256k1-related error
Secp256k1(secp256k1::Error),
/// Generation for sign nonce related error
NonceGeneration
}


Expand All @@ -47,6 +50,7 @@ impl fmt::Display for Error {
match *self {
Error::Base58(ref e) => write!(f, "base58 error: {}", e),
Error::Secp256k1(ref e) => write!(f, "secp256k1 error: {}", e),
Error::NonceGeneration => write!(f, "nonce generation error"),
}
}
}
Expand All @@ -56,6 +60,7 @@ impl error::Error for Error {
match *self {
Error::Base58(ref e) => Some(e),
Error::Secp256k1(ref e) => Some(e),
Error::NonceGeneration => None,
}
}

Expand Down Expand Up @@ -231,7 +236,7 @@ impl PrivateKey {
let pk = secp256k1::PublicKey::from_secret_key(&ctx, &self.key);

// Generate k
let mut k = secp256k1::SecretKey::new(&mut secp256k1::rand::thread_rng());
let mut k = self.generate_k(message)?;

// TODO: Check private key and k is not zero
// this is no need because all secret key instance checked.
Expand Down Expand Up @@ -260,6 +265,30 @@ impl PrivateKey {

Ok(Signature { r_x, sigma: to_bytes(&sigma) })
}

fn generate_k(&self, message: &[u8; 32]) -> Result<SecretKey, Error> {
// "SCHNORR + SHA256"
const ALGO16: [u8; 16] = [
83, 67, 72, 78, 79, 82, 82, 32, 43, 32, 83, 72, 65, 50, 53, 54
];

let mut count: u32 = 0;

loop {
let nonce = nonce_rfc6979(
message,
&self.key,
&ALGO16,
None,
count
);
count += 1;

if let Ok(k) = SecretKey::from_slice(&nonce[..]) {
return Ok(k);
}
}
}
}

fn to_bytes(sk: &secp256k1::SecretKey) -> [u8; 32] {
Expand Down
1 change: 1 addition & 0 deletions src/util/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ pub mod psbt;
pub mod uint;
pub mod signature;
pub mod prime;
pub mod rfc7969;

pub(crate) mod endian;

Expand Down
99 changes: 99 additions & 0 deletions src/util/rfc7969.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// Copyright (c) 2020 Chaintope Inc.
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

//! RFC6879
//!
use hashes::{HmacEngine, HashEngine, Hmac, Hash};
use hashes::sha256::Hash as SHA256;
use secp256k1::SecretKey;

/// Generate nonce
pub fn nonce_rfc6979(
message: &[u8; 32],
key: &SecretKey,
algo16: &[u8; 16],
data: Option<&[u8; 32]>,
counter: u32,
) -> [u8; 32]
{
let mut keydata: Vec<u8> = Vec::new();

keydata.extend(&key[..]);
keydata.extend(message);
if let Some(d) = data {
keydata.extend(d);
}
keydata.extend(algo16);
let mut rng = RFC6879::new(&keydata[..]);
let mut ret: [u8; 32] = [0u8; 32];
for _ in 0..=counter {
ret = rng.generate();
}

ret
}

struct RFC6879 {
v: [u8; 32],
k: [u8; 32],
retry: bool,
}

impl RFC6879 {
pub fn new(keydata: &[u8]) -> Self {
let mut rng = Self {
v: [1u8; 32], // RFC6979 3.2.b.
k: [0u8; 32], // RFC6979 3.2.c.
retry: false,
};

let zero = [0u8; 1];
let one = [1u8; 1];

// RFC6979 3.2.d.
let mut hmac = HmacEngine::<SHA256>::new(&rng.k[..]);
hmac.input(&rng.v[..]);
hmac.input(&zero[..]);
hmac.input(&keydata[..]);
rng.k = Hmac::from_engine(hmac).into_inner();
let mut hmac = HmacEngine::<SHA256>::new(&rng.k[..]);
hmac.input(&rng.v[..]);
rng.v = Hmac::from_engine(hmac).into_inner();

// RFC6979 2.3.f.
let mut hmac = HmacEngine::<SHA256>::new(&rng.k[..]);
hmac.input(&rng.v[..]);
hmac.input(&one[..]);
hmac.input(&keydata[..]);
rng.k = Hmac::from_engine(hmac).into_inner();
let mut hmac = HmacEngine::<SHA256>::new(&rng.k[..]);
hmac.input(&rng.v[..]);
rng.v = Hmac::from_engine(hmac).into_inner();

rng
}

pub fn generate(&mut self) -> [u8; 32] {
// RVC6979 3.2.h.
let zero = [0u8; 1];
if self.retry {
let mut hmac = HmacEngine::<SHA256>::new(&self.k[..]);
hmac.input(&self.v[..]);
hmac.input(&zero[..]);
self.k = Hmac::from_engine(hmac).into_inner();
let mut hmac = HmacEngine::<SHA256>::new(&self.k[..]);
hmac.input(&self.v[..]);
self.v = Hmac::from_engine(hmac).into_inner();
}

let mut hmac = HmacEngine::<SHA256>::new(&self.k[..]);
hmac.input(&self.v[..]);
self.v = Hmac::from_engine(hmac).into_inner();

self.retry = true;

self.v.clone()
}
}

0 comments on commit 0fdf7b0

Please sign in to comment.