feat: update ecdsautil
This commit is contained in:
@@ -4,6 +4,7 @@ use clap::{App, Arg, ArgMatches, SubCommand};
|
|||||||
use rust_util::util_clap::{Command, CommandError};
|
use rust_util::util_clap::{Command, CommandError};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use yubikey::piv::AlgorithmId;
|
use yubikey::piv::AlgorithmId;
|
||||||
|
use crate::ecdsautil::EcdsaAlgorithm;
|
||||||
use crate::keyutil::{KeyUri, YubikeyHmacEncSoftKey};
|
use crate::keyutil::{KeyUri, YubikeyHmacEncSoftKey};
|
||||||
use crate::util::base64_encode;
|
use crate::util::base64_encode;
|
||||||
|
|
||||||
@@ -47,13 +48,21 @@ impl Command for CommandImpl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let (pkcs8_base64, secret_key_pem, public_key_pem, public_key_der, jwk_ec_key) = match key_type.as_str() {
|
let ecdsa_algorithm = match key_type.as_str() {
|
||||||
"p256" => ecdsautil::generate_p256_keypair()?,
|
"p256" => EcdsaAlgorithm::P256,
|
||||||
"p384" => ecdsautil::generate_p384_keypair()?,
|
"p384" => EcdsaAlgorithm::P384,
|
||||||
_ => {
|
_ => {
|
||||||
return simple_error!("Key type must be p256 or p384");
|
return simple_error!("Key type must be p256 or p384");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let (pkcs8_base64,
|
||||||
|
secret_key_pem,
|
||||||
|
public_key_pem,
|
||||||
|
public_key_der,
|
||||||
|
jwk_ec_key
|
||||||
|
) = ecdsautil::generate_ecdsa_keypair(ecdsa_algorithm)?;
|
||||||
|
|
||||||
let (pkcs8_base64, secret_key_pem) = if with_hmac_encrypt {
|
let (pkcs8_base64, secret_key_pem) = if with_hmac_encrypt {
|
||||||
(
|
(
|
||||||
hmacutil::hmac_encrypt_from_string(&pkcs8_base64)?,
|
hmacutil::hmac_encrypt_from_string(&pkcs8_base64)?,
|
||||||
|
|||||||
@@ -36,14 +36,14 @@ pub fn parse_ecdsa_r_and_s(signature_der: &[u8]) -> XResult<(Vec<u8>, Vec<u8>)>
|
|||||||
match &seq[0].content {
|
match &seq[0].content {
|
||||||
BerObjectContent::Integer(r) => {
|
BerObjectContent::Integer(r) => {
|
||||||
debugging!("Signature r: {}", hex::encode(r));
|
debugging!("Signature r: {}", hex::encode(r));
|
||||||
vec_r = trim_point_leading_zero(r);
|
vec_r = trim_ecdsa_point_coord(r);
|
||||||
}
|
}
|
||||||
_ => return simple_error!("Parse signature failed: [0]not integer"),
|
_ => return simple_error!("Parse signature failed: [0]not integer"),
|
||||||
}
|
}
|
||||||
match &seq[1].content {
|
match &seq[1].content {
|
||||||
BerObjectContent::Integer(s) => {
|
BerObjectContent::Integer(s) => {
|
||||||
debugging!("Signature s: {}", hex::encode(s));
|
debugging!("Signature s: {}", hex::encode(s));
|
||||||
vec_s = trim_point_leading_zero(s);
|
vec_s = trim_ecdsa_point_coord(s);
|
||||||
}
|
}
|
||||||
_ => return simple_error!("Parse signature failed: [1]not integer"),
|
_ => return simple_error!("Parse signature failed: [1]not integer"),
|
||||||
}
|
}
|
||||||
@@ -53,32 +53,47 @@ pub fn parse_ecdsa_r_and_s(signature_der: &[u8]) -> XResult<(Vec<u8>, Vec<u8>)>
|
|||||||
Ok((vec_r, vec_s))
|
Ok((vec_r, vec_s))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trim_point_leading_zero(p: &[u8]) -> Vec<u8> {
|
fn trim_ecdsa_point_coord(p: &[u8]) -> Vec<u8> {
|
||||||
if p.len() == ((256 / 8) + 1) || p.len() == ((384 / 8) + 1) {
|
if p.len() == ((256 / 8) + 1) || p.len() == ((384 / 8) + 1) {
|
||||||
p[1..].to_vec()
|
p[1..].to_vec()
|
||||||
|
} else if p.len() == ((256 / 8) - 1) || p.len() == ((384 / 8) - 1) {
|
||||||
|
let mut v = vec![];
|
||||||
|
v.push(0_u8);
|
||||||
|
v.extend_from_slice(p);
|
||||||
|
v
|
||||||
} else {
|
} else {
|
||||||
p.to_vec()
|
p.to_vec()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_p256_keypair() -> XResult<(String, String, String, Vec<u8>, JwkEcKey)> {
|
|
||||||
let secret_key = p256::SecretKey::random(&mut rand::thread_rng());
|
macro_rules! generate_inner_ecdsa_keypair {
|
||||||
|
($algo: tt) => ({
|
||||||
|
use $algo::SecretKey;
|
||||||
|
|
||||||
|
let secret_key = SecretKey::random(&mut rand::thread_rng());
|
||||||
let secret_key_der_base64 = base64_encode(secret_key.to_pkcs8_der()?.as_bytes());
|
let secret_key_der_base64 = base64_encode(secret_key.to_pkcs8_der()?.as_bytes());
|
||||||
let secret_key_pem = secret_key.to_pkcs8_pem(LineEnding::LF)?.to_string();
|
let secret_key_pem = secret_key.to_pkcs8_pem(LineEnding::LF)?.to_string();
|
||||||
let public_key_pem = secret_key.public_key().to_public_key_pem(LineEnding::LF)?;
|
let public_key_pem = secret_key.public_key().to_public_key_pem(LineEnding::LF)?;
|
||||||
let public_key_der = secret_key.public_key().to_public_key_der()?.to_vec();
|
let public_key_der = secret_key.public_key().to_public_key_der()?.to_vec();
|
||||||
let jwk_ec_key = secret_key.public_key().to_jwk();
|
let jwk_ec_key = secret_key.public_key().to_jwk();
|
||||||
Ok((secret_key_der_base64, secret_key_pem, public_key_pem, public_key_der, jwk_ec_key))
|
Ok((secret_key_der_base64, secret_key_pem, public_key_pem, public_key_der, jwk_ec_key))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn generate_ecdsa_keypair(algo: EcdsaAlgorithm) -> XResult<(String, String, String, Vec<u8>, JwkEcKey)> {
|
||||||
|
match algo {
|
||||||
|
EcdsaAlgorithm::P256 => generate_p256_keypair(),
|
||||||
|
EcdsaAlgorithm::P384 => generate_p384_keypair(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn generate_p256_keypair() -> XResult<(String, String, String, Vec<u8>, JwkEcKey)> {
|
||||||
|
generate_inner_ecdsa_keypair!(p256)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_p384_keypair() -> XResult<(String, String, String, Vec<u8>, JwkEcKey)> {
|
pub fn generate_p384_keypair() -> XResult<(String, String, String, Vec<u8>, JwkEcKey)> {
|
||||||
let secret_key = p384::SecretKey::random(&mut rand::thread_rng());
|
generate_inner_ecdsa_keypair!(p384)
|
||||||
let secret_key_der_base64 = base64_encode(secret_key.to_pkcs8_der()?.as_bytes());
|
|
||||||
let secret_key_pem = secret_key.to_pkcs8_pem(LineEnding::LF)?.to_string();
|
|
||||||
let public_key_pem = secret_key.public_key().to_public_key_pem(LineEnding::LF)?;
|
|
||||||
let public_key_der = secret_key.public_key().to_public_key_der()?.to_vec();
|
|
||||||
let jwk_ec_key = secret_key.public_key().to_jwk();
|
|
||||||
Ok((secret_key_der_base64, secret_key_pem, public_key_pem, public_key_der, jwk_ec_key))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -110,6 +125,7 @@ pub fn parse_p384_private_key_to_public_key(private_key_pkcs8: &str) -> XResult<
|
|||||||
parse_ecdsa_private_key_to_public_key!(p384, private_key_pkcs8)
|
parse_ecdsa_private_key_to_public_key!(p384, private_key_pkcs8)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
macro_rules! parse_ecdsa_private_key {
|
macro_rules! parse_ecdsa_private_key {
|
||||||
($algo: tt, $parse_ecdsa_private_key: tt) => ({
|
($algo: tt, $parse_ecdsa_private_key: tt) => ({
|
||||||
use $algo::pkcs8::DecodePrivateKey;
|
use $algo::pkcs8::DecodePrivateKey;
|
||||||
@@ -137,6 +153,7 @@ pub fn parse_p384_private_key(private_key_pkcs8: &str) -> XResult<Vec<u8>> {
|
|||||||
parse_ecdsa_private_key!(p384, private_key_pkcs8)
|
parse_ecdsa_private_key!(p384, private_key_pkcs8)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
macro_rules! sign_ecdsa_rs_or_der {
|
macro_rules! sign_ecdsa_rs_or_der {
|
||||||
($algo: tt, $private_key_d: tt, $pre_hash: tt, $is_rs: tt) => ({
|
($algo: tt, $private_key_d: tt, $pre_hash: tt, $is_rs: tt) => ({
|
||||||
use $algo::ecdsa::{SigningKey, Signature};
|
use $algo::ecdsa::{SigningKey, Signature};
|
||||||
@@ -168,6 +185,7 @@ pub fn sign_p384_rs_or_der(private_key_d: &[u8], pre_hash: &[u8], is_rs: bool) -
|
|||||||
sign_ecdsa_rs_or_der!(p384, private_key_d, pre_hash, is_rs)
|
sign_ecdsa_rs_or_der!(p384, private_key_d, pre_hash, is_rs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
macro_rules! ecdsa_verify_signature {
|
macro_rules! ecdsa_verify_signature {
|
||||||
($algo: tt, $pk_point: tt, $prehash: tt, $signature: tt) => ({
|
($algo: tt, $pk_point: tt, $prehash: tt, $signature: tt) => ({
|
||||||
use ecdsa::Signature;
|
use ecdsa::Signature;
|
||||||
|
|||||||
Reference in New Issue
Block a user