feat: fix sign jwt
This commit is contained in:
@@ -11,6 +11,7 @@ use yubikey::{Certificate, YubiKey};
|
||||
use yubikey::piv::{AlgorithmId, sign_data, SlotId};
|
||||
|
||||
use crate::{digest, pivutil, rsautil, util};
|
||||
use crate::ecdsautil::parse_ecdsa_to_rs;
|
||||
|
||||
const SEPARATOR: &str = ".";
|
||||
|
||||
@@ -153,8 +154,13 @@ fn sign_jwt(yk: &mut YubiKey, slot_id: SlotId, pin_opt: &Option<String>, mut hea
|
||||
|
||||
let signed_data = opt_result!(
|
||||
sign_data(yk, &raw_in, yk_algorithm, slot_id), "Sign YubiKey failed: {}");
|
||||
let signed_data = match jwt_algorithm {
|
||||
AlgorithmType::Rs256 => signed_data.to_vec(),
|
||||
AlgorithmType::Es256 | AlgorithmType::Es384 => parse_ecdsa_to_rs(signed_data.as_slice())?,
|
||||
_ => return simple_error!("SHOULD NOT HAPPEN: {:?}", jwt_algorithm),
|
||||
};
|
||||
|
||||
let signature = util::base64_encode_url_safe_no_pad(signed_data);
|
||||
let signature = util::base64_encode_url_safe_no_pad(&signed_data);
|
||||
|
||||
Ok([&*header, &*claims, &signature].join(SEPARATOR))
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use der_parser::ber::BerObjectContent;
|
||||
use ecdsa::VerifyingKey;
|
||||
use p256::NistP256;
|
||||
use p256::ecdsa::signature::hazmat::PrehashVerifier;
|
||||
@@ -11,6 +12,46 @@ pub enum EcdsaAlgorithm {
|
||||
P384,
|
||||
}
|
||||
|
||||
pub fn parse_ecdsa_to_rs(signature_der: &[u8]) -> XResult<Vec<u8>> {
|
||||
let (mut r, s)= parse_ecdsa_r_and_s(signature_der)?;
|
||||
r.extend_from_slice(&s);
|
||||
Ok(r)
|
||||
}
|
||||
|
||||
pub fn parse_ecdsa_r_and_s(signature_der: &[u8]) -> XResult<(Vec<u8>, Vec<u8>)> {
|
||||
let mut vec_r: Vec<u8> = Vec::new();
|
||||
let mut vec_s: Vec<u8> = Vec::new();
|
||||
let (_, parsed_signature) = opt_result!(der_parser::parse_der(signature_der), "Parse signature failed: {}");
|
||||
match parsed_signature.content {
|
||||
BerObjectContent::Sequence(seq) => {
|
||||
match &seq[0].content {
|
||||
BerObjectContent::Integer(r) => {
|
||||
debugging!("Signature r: {}", hex::encode(r));
|
||||
if r.len() == ((256 / 8) + 1) || r.len() == ((384 / 8) + 1) {
|
||||
vec_r = r[1..].to_vec();
|
||||
} else {
|
||||
vec_r = r.to_vec();
|
||||
}
|
||||
}
|
||||
_ => return simple_error!("Parse signature failed: [0]not integer"),
|
||||
}
|
||||
match &seq[1].content {
|
||||
BerObjectContent::Integer(s) => {
|
||||
debugging!("Signature s: {}", hex::encode(s));
|
||||
if s.len() == ((256 / 8) + 1) || s.len() == ((384 / 8) + 1) {
|
||||
vec_s = s[1..].to_vec();
|
||||
} else {
|
||||
vec_s = s.to_vec();
|
||||
}
|
||||
}
|
||||
_ => return simple_error!("Parse signature failed: [1]not integer"),
|
||||
}
|
||||
}
|
||||
_ => return simple_error!("Parse signature failed: not sequence"),
|
||||
}
|
||||
Ok((vec_r, vec_s))
|
||||
}
|
||||
|
||||
macro_rules! ecdsa_verify_signature {
|
||||
($algo: tt, $pk_point: tt, $prehash: tt, $signature: tt) => ({
|
||||
let verifying_key: VerifyingKey<$algo> = opt_result!(VerifyingKey::<$algo>::from_sec1_bytes($pk_point), "Parse public key failed: {}");
|
||||
|
||||
Reference in New Issue
Block a user