From c7f173b43e97afa0140117b30d4b16b85388b429 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sun, 4 Apr 2021 16:13:57 +1200 Subject: [PATCH] Rework Recipient to wrap p256::PublicKey --- src/builder.rs | 2 +- src/main.rs | 8 ++++---- src/p256.rs | 32 +++++++++++++------------------- 3 files changed, 18 insertions(+), 24 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 7f05680..f09c902 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -113,7 +113,7 @@ impl IdentityBuilder { let recipient = match &generated { PublicKeyInfo::EcP256(pubkey) => { - Recipient::from_pubkey(*pubkey).expect("YubiKey generates a valid pubkey") + Recipient::from_encoded(pubkey).expect("YubiKey generates a valid pubkey") } _ => unreachable!(), }; diff --git a/src/main.rs b/src/main.rs index 37db34f..916dacf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -137,7 +137,7 @@ fn identity(opts: PluginOptions) -> Result<(), Error> { // - Only P-256 keys are compatible with us. match (key.slot(), key.certificate().subject_pki()) { (SlotId::Retired(slot), PublicKeyInfo::EcP256(pubkey)) => { - p256::Recipient::from_pubkey(*pubkey).map(|r| (key, slot, r)) + p256::Recipient::from_encoded(pubkey).map(|r| (key, slot, r)) } _ => None, } @@ -205,7 +205,7 @@ fn list(all: bool) -> Result<(), Error> { // Only P-256 keys are compatible with us. let recipient = match key.certificate().subject_pki() { - PublicKeyInfo::EcP256(pubkey) => match p256::Recipient::from_pubkey(*pubkey) { + PublicKeyInfo::EcP256(pubkey) => match p256::Recipient::from_encoded(pubkey) { Some(recipient) => recipient, None => continue, }, @@ -342,7 +342,7 @@ fn main() -> Result<(), Error> { .find(|key| key.slot() == SlotId::Retired(slot)) .map(|key| match key.certificate().subject_pki() { PublicKeyInfo::EcP256(pubkey) => { - p256::Recipient::from_pubkey(*pubkey).map(|_| { + p256::Recipient::from_encoded(pubkey).map(|_| { // Cache the details we need to display to the user. let (_, cert) = x509_parser::parse_x509_certificate(key.certificate().as_ref()) @@ -394,7 +394,7 @@ fn main() -> Result<(), Error> { if let Some(key) = keys.iter().find(|key| key.slot() == SlotId::Retired(slot)) { let recipient = match key.certificate().subject_pki() { PublicKeyInfo::EcP256(pubkey) => { - p256::Recipient::from_pubkey(*pubkey).expect("We checked this above") + p256::Recipient::from_encoded(pubkey).expect("We checked this above") } _ => unreachable!(), }; diff --git a/src/p256.rs b/src/p256.rs index 53e5954..370af2c 100644 --- a/src/p256.rs +++ b/src/p256.rs @@ -1,6 +1,5 @@ use bech32::{ToBase32, Variant}; -use elliptic_curve::sec1::EncodedPoint; -use p256::NistP256; +use elliptic_curve::sec1::{FromEncodedPoint, ToEncodedPoint}; use sha2::{Digest, Sha256}; use std::convert::TryInto; use std::fmt; @@ -11,11 +10,11 @@ pub(crate) const TAG_BYTES: usize = 4; /// Wrapper around a compressed secp256r1 curve point. #[derive(Clone)] -pub struct Recipient(EncodedPoint); +pub struct Recipient(p256::PublicKey); impl fmt::Debug for Recipient { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "Recipient({:?})", self.as_bytes()) + write!(f, "Recipient({:?})", self.to_encoded().as_bytes()) } } @@ -24,7 +23,7 @@ impl fmt::Display for Recipient { f.write_str( bech32::encode( RECIPIENT_PREFIX, - self.as_bytes().to_base32(), + self.to_encoded().as_bytes().to_base32(), Variant::Bech32, ) .expect("HRP is valid") @@ -34,22 +33,17 @@ impl fmt::Display for Recipient { } impl Recipient { - /// Attempts to parse a valid secp256r1 public key from its SEC-1 encoding. - pub(crate) fn from_pubkey(pubkey: EncodedPoint) -> Option { - if pubkey.is_compressed() { - if pubkey.decompress().is_some().into() { - Some(Recipient(pubkey)) - } else { - None - } - } else { - Some(Recipient(pubkey.compress())) - } + /// Attempts to parse a valid YubiKey recipient from its SEC-1 encoding. + /// + /// This accepts both compressed (as used by the plugin) and uncompressed (as used in + /// the YubiKey certificate) encodings. + pub(crate) fn from_encoded(encoded: &p256::EncodedPoint) -> Option { + p256::PublicKey::from_encoded_point(&encoded).map(Recipient) } - /// Returns the compressed SEC-1 encoding of this public key. - pub(crate) fn as_bytes(&self) -> &[u8] { - self.0.as_bytes() + /// Returns the compressed SEC-1 encoding of this recipient. + pub(crate) fn to_encoded(&self) -> p256::EncodedPoint { + self.0.to_encoded_point(true) } pub(crate) fn tag(&self) -> [u8; TAG_BYTES] {