Skip to content

Commit

Permalink
ecdsa,dsa,ed25519,ed448: pkcs8 API changes (#851)
Browse files Browse the repository at this point in the history
Signed-off-by: Arthur Gautier <baloo@superbaloo.net>
  • Loading branch information
baloo authored Sep 5, 2024
1 parent 4da24fb commit cf81fb3
Show file tree
Hide file tree
Showing 8 changed files with 62 additions and 39 deletions.
17 changes: 7 additions & 10 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,9 @@ members = [

[profile.dev]
opt-level = 2

[patch.crates-io]
sec1 = { git = "https://github.com/RustCrypto/formats.git" }
pkcs8 = { git = "https://github.com/RustCrypto/formats.git" }
# https://github.com/RustCrypto/traits/pull/1650
elliptic-curve = { git = "https://github.com/baloo/traits.git", branch = "baloo/elliptic-curve/pkcs8-API-break" }
18 changes: 11 additions & 7 deletions dsa/src/signing_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@ use digest::{core_api::BlockSizeUser, Digest, FixedOutputReset};
use num_bigint::BigUint;
use num_traits::Zero;
use pkcs8::{
der::{asn1::UintRef, AnyRef, Decode, Encode},
AlgorithmIdentifierRef, EncodePrivateKey, PrivateKeyInfo, SecretDocument,
der::{
asn1::{OctetStringRef, UintRef},
AnyRef, Decode, Encode,
},
AlgorithmIdentifierRef, EncodePrivateKey, PrivateKeyInfoRef, SecretDocument,
};
use signature::{
hazmat::{PrehashSigner, RandomizedPrehashSigner},
Expand Down Expand Up @@ -182,7 +185,8 @@ impl EncodePrivateKey for SigningKey {
let x = UintRef::new(&x_bytes)?;
let mut signing_key = x.to_der()?;

let signing_key_info = PrivateKeyInfo::new(algorithm, &signing_key);
let signing_key_info =
PrivateKeyInfoRef::new(algorithm, OctetStringRef::new(&signing_key)?);
let secret_document = signing_key_info.try_into()?;

signing_key.zeroize();
Expand All @@ -192,19 +196,19 @@ impl EncodePrivateKey for SigningKey {
}
}

impl<'a> TryFrom<PrivateKeyInfo<'a>> for SigningKey {
impl<'a> TryFrom<PrivateKeyInfoRef<'a>> for SigningKey {
type Error = pkcs8::Error;

fn try_from(value: PrivateKeyInfo<'a>) -> Result<Self, Self::Error> {
fn try_from(value: PrivateKeyInfoRef<'a>) -> Result<Self, Self::Error> {
value.algorithm.assert_algorithm_oid(OID)?;

let parameters = value.algorithm.parameters_any()?;
let components = parameters.decode_as::<Components>()?;

let x = UintRef::from_der(value.private_key)?;
let x = UintRef::from_der(value.private_key.as_bytes())?;
let x = BigUint::from_bytes_be(x.as_bytes());

let y = if let Some(y_bytes) = value.public_key {
let y = if let Some(y_bytes) = value.public_key.as_ref().and_then(|bs| bs.as_bytes()) {
let y = UintRef::from_der(y_bytes)?;
BigUint::from_bytes_be(y.as_bytes())
} else {
Expand Down
2 changes: 1 addition & 1 deletion ecdsa/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ elliptic-curve = { version = "=0.14.0-pre.6", default-features = false, features
signature = { version = "=2.3.0-pre.4", default-features = false, features = ["rand_core"] }

# optional dependencies
der = { version = "0.8.0-rc.0", optional = true }
der = { version = "0.8.0-rc.1", optional = true }
digest = { version = "=0.11.0-pre.9", optional = true, default-features = false, features = ["oid"] }
rfc6979 = { version = "=0.5.0-pre.4", optional = true, path = "../rfc6979" }
serdect = { version = "0.2", optional = true, default-features = false, features = ["alloc"] }
Expand Down
6 changes: 3 additions & 3 deletions ecdsa/src/der.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use core::{
fmt::{self, Debug},
ops::{Add, Range},
};
use der::{asn1::UintRef, Decode, Encode, FixedTag, Length, Reader, Tag, Writer};
use der::{asn1::UintRef, Decode, Encode, FixedTag, Header, Length, Reader, Tag, Writer};
use elliptic_curve::{
array::{typenum::Unsigned, Array, ArraySize},
consts::U9,
Expand Down Expand Up @@ -206,7 +206,7 @@ where
type Error = der::Error;

fn decode<R: Reader<'a>>(reader: &mut R) -> der::Result<Self> {
let header = reader.peek_header()?;
let header = Header::peek(reader)?;
header.tag.assert_eq(Tag::Sequence)?;

let mut buf = SignatureBytes::<C>::default();
Expand Down Expand Up @@ -359,7 +359,7 @@ where
/// Decode the `r` and `s` components of a DER-encoded ECDSA signature.
fn decode_der(der_bytes: &[u8]) -> der::Result<(UintRef<'_>, UintRef<'_>)> {
let mut reader = der::SliceReader::new(der_bytes)?;
let header = der::Header::decode(&mut reader)?;
let header = Header::decode(&mut reader)?;
header.tag.assert_eq(Tag::Sequence)?;

let ret = reader.read_nested::<_, _, der::Error>(header.length, |reader| {
Expand Down
4 changes: 2 additions & 2 deletions ecdsa/src/signing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,7 @@ where
}

#[cfg(feature = "pkcs8")]
impl<C> TryFrom<pkcs8::PrivateKeyInfo<'_>> for SigningKey<C>
impl<C> TryFrom<pkcs8::PrivateKeyInfoRef<'_>> for SigningKey<C>
where
C: EcdsaCurve + AssociatedOid + CurveArithmetic,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
Expand All @@ -555,7 +555,7 @@ where
{
type Error = pkcs8::Error;

fn try_from(private_key_info: pkcs8::PrivateKeyInfo<'_>) -> pkcs8::Result<Self> {
fn try_from(private_key_info: pkcs8::PrivateKeyInfoRef<'_>) -> pkcs8::Result<Self> {
SecretKey::try_from(private_key_info).map(Into::into)
}
}
Expand Down
24 changes: 16 additions & 8 deletions ed25519/src/pkcs8.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,17 @@
//! breaking changes when using this module.

pub use pkcs8::{
spki, DecodePrivateKey, DecodePublicKey, Error, ObjectIdentifier, PrivateKeyInfo, Result,
spki, DecodePrivateKey, DecodePublicKey, Error, ObjectIdentifier, PrivateKeyInfoRef, Result,
};

#[cfg(feature = "alloc")]
pub use pkcs8::{spki::EncodePublicKey, EncodePrivateKey};

#[cfg(feature = "alloc")]
pub use pkcs8::der::{asn1::BitStringRef, Document, SecretDocument};
pub use pkcs8::der::{
asn1::{BitStringRef, OctetStringRef},
Document, SecretDocument,
};

use core::fmt;

Expand Down Expand Up @@ -128,10 +131,14 @@ impl EncodePrivateKey for KeypairBytes {
private_key[1] = 0x20;
private_key[2..].copy_from_slice(&self.secret_key);

let private_key_info = PrivateKeyInfo {
let private_key_info = PrivateKeyInfoRef {
algorithm: ALGORITHM_ID,
private_key: &private_key,
public_key: self.public_key.as_ref().map(|pk| pk.0.as_slice()),
private_key: OctetStringRef::new(&private_key)?,
public_key: self
.public_key
.as_ref()
.map(|pk| BitStringRef::new(0, &pk.0))
.transpose()?,
};

let result = SecretDocument::encode_msg(&private_key_info)?;
Expand All @@ -143,10 +150,10 @@ impl EncodePrivateKey for KeypairBytes {
}
}

impl TryFrom<PrivateKeyInfo<'_>> for KeypairBytes {
impl TryFrom<PrivateKeyInfoRef<'_>> for KeypairBytes {
type Error = Error;

fn try_from(private_key: PrivateKeyInfo<'_>) -> Result<Self> {
fn try_from(private_key: PrivateKeyInfoRef<'_>) -> Result<Self> {
private_key.algorithm.assert_algorithm_oid(ALGORITHM_OID)?;

if private_key.algorithm.parameters.is_some() {
Expand All @@ -161,13 +168,14 @@ impl TryFrom<PrivateKeyInfo<'_>> for KeypairBytes {
//
// - 0x04: OCTET STRING tag
// - 0x20: 32-byte length
let secret_key = match private_key.private_key {
let secret_key = match private_key.private_key.as_bytes() {
[0x04, 0x20, rest @ ..] => rest.try_into().map_err(|_| Error::KeyMalformed),
_ => Err(Error::KeyMalformed),
}?;

let public_key = private_key
.public_key
.and_then(|bs| bs.as_bytes())
.map(|bytes| bytes.try_into().map_err(|_| Error::KeyMalformed))
.transpose()?
.map(PublicKeyBytes);
Expand Down
24 changes: 16 additions & 8 deletions ed448/src/pkcs8.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,17 @@
//! breaking changes when using this module.

pub use pkcs8::{
spki, DecodePrivateKey, DecodePublicKey, Error, ObjectIdentifier, PrivateKeyInfo, Result,
spki, DecodePrivateKey, DecodePublicKey, Error, ObjectIdentifier, PrivateKeyInfoRef, Result,
};

#[cfg(feature = "alloc")]
pub use pkcs8::{spki::EncodePublicKey, EncodePrivateKey};

#[cfg(feature = "alloc")]
pub use pkcs8::der::{asn1::BitStringRef, Document, SecretDocument};
pub use pkcs8::der::{
asn1::{BitStringRef, OctetStringRef},
Document, SecretDocument,
};

#[cfg(feature = "zeroize")]
use zeroize::Zeroize;
Expand Down Expand Up @@ -122,10 +125,14 @@ impl EncodePrivateKey for KeypairBytes {
private_key[1] = 0x39;
private_key[2..].copy_from_slice(&self.secret_key);

let private_key_info = PrivateKeyInfo {
let private_key_info = PrivateKeyInfoRef {
algorithm: ALGORITHM_ID,
private_key: &private_key,
public_key: self.public_key.as_ref().map(|pk| pk.0.as_slice()),
private_key: OctetStringRef::new(&private_key)?,
public_key: self
.public_key
.as_ref()
.map(|pk| BitStringRef::new(0, &pk.0))
.transpose()?,
};
let result = SecretDocument::encode_msg(&private_key_info)?;

Expand All @@ -136,10 +143,10 @@ impl EncodePrivateKey for KeypairBytes {
}
}

impl TryFrom<PrivateKeyInfo<'_>> for KeypairBytes {
impl TryFrom<PrivateKeyInfoRef<'_>> for KeypairBytes {
type Error = Error;

fn try_from(private_key: PrivateKeyInfo<'_>) -> Result<Self> {
fn try_from(private_key: PrivateKeyInfoRef<'_>) -> Result<Self> {
private_key.algorithm.assert_algorithm_oid(ALGORITHM_OID)?;

if private_key.algorithm.parameters.is_some() {
Expand All @@ -154,13 +161,14 @@ impl TryFrom<PrivateKeyInfo<'_>> for KeypairBytes {
//
// - 0x04: OCTET STRING tag
// - 0x39: 57-byte length
let secret_key = match private_key.private_key {
let secret_key = match private_key.private_key.as_bytes() {
[0x04, 0x39, rest @ ..] => rest.try_into().map_err(|_| Error::KeyMalformed),
_ => Err(Error::KeyMalformed),
}?;

let public_key = private_key
.public_key
.and_then(|bs| bs.as_bytes())
.map(|bytes| bytes.try_into().map_err(|_| Error::KeyMalformed))
.transpose()?
.map(PublicKeyBytes);
Expand Down

0 comments on commit cf81fb3

Please sign in to comment.