Skip to content

Commit 009d84a

Browse files
committed
feat: add ES512 algorithm support using P-521 elliptic curve
1 parent 53a3fc2 commit 009d84a

6 files changed

Lines changed: 79 additions & 7 deletions

File tree

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ ed25519-dalek = { version = "2.1.1", optional = true, features = ["pkcs8"] }
4040
hmac = { version = "0.12.1", optional = true }
4141
p256 = { version = "0.13.2", optional = true, features = ["ecdsa"] }
4242
p384 = { version = "0.13.0", optional = true, features = ["ecdsa"] }
43+
p521 = { version = "0.13.0", optional = true, features = ["ecdsa"] }
4344
rand = { version = "0.8.5", optional = true, features = ["std"], default-features = false }
4445
rsa = { version = "0.9.6", optional = true }
4546
sha2 = { version = "0.10.7", optional = true, features = ["oid"] }
@@ -66,7 +67,7 @@ criterion = { version = "0.4", default-features = false }
6667
[features]
6768
default = ["use_pem"]
6869
use_pem = ["pem", "simple_asn1"]
69-
rust_crypto = ["ed25519-dalek", "hmac", "p256", "p384", "rand", "rsa", "sha2"]
70+
rust_crypto = ["ed25519-dalek", "hmac", "p256", "p384", "p521", "rand", "rsa", "sha2"]
7071
aws_lc_rs = ["aws-lc-rs"]
7172

7273
[[bench]]

src/algorithms.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ impl AlgorithmFamily {
2525
Algorithm::PS384,
2626
Algorithm::PS512,
2727
],
28-
Self::Ec => &[Algorithm::ES256, Algorithm::ES384],
28+
Self::Ec => &[Algorithm::ES256, Algorithm::ES384, Algorithm::ES512],
2929
Self::Ed => &[Algorithm::EdDSA],
3030
}
3131
}
@@ -47,6 +47,8 @@ pub enum Algorithm {
4747
ES256,
4848
/// ECDSA using SHA-384
4949
ES384,
50+
/// ECDSA using SHA-512
51+
ES512,
5052

5153
/// RSASSA-PKCS1-v1_5 using SHA-256
5254
RS256,
@@ -75,6 +77,7 @@ impl FromStr for Algorithm {
7577
"HS512" => Ok(Algorithm::HS512),
7678
"ES256" => Ok(Algorithm::ES256),
7779
"ES384" => Ok(Algorithm::ES384),
80+
"ES512" => Ok(Algorithm::ES512),
7881
"RS256" => Ok(Algorithm::RS256),
7982
"RS384" => Ok(Algorithm::RS384),
8083
"PS256" => Ok(Algorithm::PS256),
@@ -97,7 +100,7 @@ impl Algorithm {
97100
| Algorithm::PS256
98101
| Algorithm::PS384
99102
| Algorithm::PS512 => AlgorithmFamily::Rsa,
100-
Algorithm::ES256 | Algorithm::ES384 => AlgorithmFamily::Ec,
103+
Algorithm::ES256 | Algorithm::ES384 | Algorithm::ES512 => AlgorithmFamily::Ec,
101104
Algorithm::EdDSA => AlgorithmFamily::Ed,
102105
}
103106
}

src/crypto/rust_crypto/ecdsa.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ use p256::ecdsa::{
1111
use p384::ecdsa::{
1212
Signature as Signature384, SigningKey as SigningKey384, VerifyingKey as VerifyingKey384,
1313
};
14+
use p521::ecdsa::{
15+
Signature as Signature521, SigningKey as SigningKey521, VerifyingKey as VerifyingKey521,
16+
};
1417
use rsa::pkcs8::DecodePrivateKey;
1518
use signature::{Error, Signer, Verifier};
1619

@@ -85,3 +88,62 @@ define_ecdsa_signer!(Es384Signer, Algorithm::ES384, SigningKey384);
8588

8689
define_ecdsa_verifier!(Es256Verifier, Algorithm::ES256, VerifyingKey256, Signature256);
8790
define_ecdsa_verifier!(Es384Verifier, Algorithm::ES384, VerifyingKey384, Signature384);
91+
92+
// P521 (ES512) uses a different API - no sign_recoverable
93+
pub struct Es512Signer(SigningKey521);
94+
95+
impl Es512Signer {
96+
pub(crate) fn new(encoding_key: &EncodingKey) -> Result<Self> {
97+
if encoding_key.family != AlgorithmFamily::Ec {
98+
return Err(new_error(ErrorKind::InvalidKeyFormat));
99+
}
100+
101+
Ok(Self(
102+
SigningKey521::from_bytes(encoding_key.inner().into())
103+
.map_err(|_| ErrorKind::InvalidEcdsaKey)?,
104+
))
105+
}
106+
}
107+
108+
impl Signer<Vec<u8>> for Es512Signer {
109+
fn try_sign(&self, msg: &[u8]) -> std::result::Result<Vec<u8>, Error> {
110+
let signature: Signature521 = self.0.sign(msg);
111+
Ok(signature.to_vec())
112+
}
113+
}
114+
115+
impl JwtSigner for Es512Signer {
116+
fn algorithm(&self) -> Algorithm {
117+
Algorithm::ES512
118+
}
119+
}
120+
121+
pub struct Es512Verifier(VerifyingKey521);
122+
123+
impl Es512Verifier {
124+
pub(crate) fn new(decoding_key: &DecodingKey) -> Result<Self> {
125+
if decoding_key.family != AlgorithmFamily::Ec {
126+
return Err(new_error(ErrorKind::InvalidKeyFormat));
127+
}
128+
129+
Ok(Self(
130+
VerifyingKey521::from_sec1_bytes(decoding_key.as_bytes())
131+
.map_err(|_| ErrorKind::InvalidEcdsaKey)?,
132+
))
133+
}
134+
}
135+
136+
impl Verifier<Vec<u8>> for Es512Verifier {
137+
fn verify(&self, msg: &[u8], signature: &Vec<u8>) -> std::result::Result<(), Error> {
138+
self.0
139+
.verify(msg, &Signature521::from_slice(signature).map_err(Error::from_source)?)
140+
.map_err(Error::from_source)?;
141+
Ok(())
142+
}
143+
}
144+
145+
impl JwtVerifier for Es512Verifier {
146+
fn algorithm(&self) -> Algorithm {
147+
Algorithm::ES512
148+
}
149+
}

src/decoding.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use crate::validation::{Validation, validate};
1616
// Crypto
1717
#[cfg(feature = "aws_lc_rs")]
1818
use crate::crypto::aws_lc::{
19-
ecdsa::{Es256Verifier, Es384Verifier},
19+
ecdsa::{Es256Verifier, Es384Verifier, Es512Verifier},
2020
eddsa::EdDSAVerifier,
2121
hmac::{Hs256Verifier, Hs384Verifier, Hs512Verifier},
2222
rsa::{
@@ -26,7 +26,7 @@ use crate::crypto::aws_lc::{
2626
};
2727
#[cfg(feature = "rust_crypto")]
2828
use crate::crypto::rust_crypto::{
29-
ecdsa::{Es256Verifier, Es384Verifier},
29+
ecdsa::{Es256Verifier, Es384Verifier, Es512Verifier},
3030
eddsa::EdDSAVerifier,
3131
hmac::{Hs256Verifier, Hs384Verifier, Hs512Verifier},
3232
rsa::{
@@ -326,6 +326,7 @@ pub fn jwt_verifier_factory(
326326
Algorithm::HS512 => Box::new(Hs512Verifier::new(key)?) as Box<dyn JwtVerifier>,
327327
Algorithm::ES256 => Box::new(Es256Verifier::new(key)?) as Box<dyn JwtVerifier>,
328328
Algorithm::ES384 => Box::new(Es384Verifier::new(key)?) as Box<dyn JwtVerifier>,
329+
Algorithm::ES512 => Box::new(Es512Verifier::new(key)?) as Box<dyn JwtVerifier>,
329330
Algorithm::RS256 => Box::new(Rsa256Verifier::new(key)?) as Box<dyn JwtVerifier>,
330331
Algorithm::RS384 => Box::new(Rsa384Verifier::new(key)?) as Box<dyn JwtVerifier>,
331332
Algorithm::RS512 => Box::new(Rsa512Verifier::new(key)?) as Box<dyn JwtVerifier>,

src/encoding.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use crate::serialization::{b64_encode, b64_encode_part};
1717
// Crypto
1818
#[cfg(feature = "aws_lc_rs")]
1919
use crate::crypto::aws_lc::{
20-
ecdsa::{Es256Signer, Es384Signer},
20+
ecdsa::{Es256Signer, Es384Signer, Es512Signer},
2121
eddsa::EdDSASigner,
2222
hmac::{Hs256Signer, Hs384Signer, Hs512Signer},
2323
rsa::{
@@ -26,7 +26,7 @@ use crate::crypto::aws_lc::{
2626
};
2727
#[cfg(feature = "rust_crypto")]
2828
use crate::crypto::rust_crypto::{
29-
ecdsa::{Es256Signer, Es384Signer},
29+
ecdsa::{Es256Signer, Es384Signer, Es512Signer},
3030
eddsa::EdDSASigner,
3131
hmac::{Hs256Signer, Hs384Signer, Hs512Signer},
3232
rsa::{
@@ -202,6 +202,7 @@ pub(crate) fn jwt_signer_factory(
202202
Algorithm::HS512 => Box::new(Hs512Signer::new(key)?) as Box<dyn JwtSigner>,
203203
Algorithm::ES256 => Box::new(Es256Signer::new(key)?) as Box<dyn JwtSigner>,
204204
Algorithm::ES384 => Box::new(Es384Signer::new(key)?) as Box<dyn JwtSigner>,
205+
Algorithm::ES512 => Box::new(Es512Signer::new(key)?) as Box<dyn JwtSigner>,
205206
Algorithm::RS256 => Box::new(Rsa256Signer::new(key)?) as Box<dyn JwtSigner>,
206207
Algorithm::RS384 => Box::new(Rsa384Signer::new(key)?) as Box<dyn JwtSigner>,
207208
Algorithm::RS512 => Box::new(Rsa512Signer::new(key)?) as Box<dyn JwtSigner>,

src/jwk.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,8 @@ pub enum KeyAlgorithm {
176176
ES256,
177177
/// ECDSA using SHA-384
178178
ES384,
179+
/// ECDSA using SHA-512
180+
ES512,
179181

180182
/// RSASSA-PKCS1-v1_5 using SHA-256
181183
RS256,
@@ -219,6 +221,7 @@ impl FromStr for KeyAlgorithm {
219221
"HS512" => Ok(KeyAlgorithm::HS512),
220222
"ES256" => Ok(KeyAlgorithm::ES256),
221223
"ES384" => Ok(KeyAlgorithm::ES384),
224+
"ES512" => Ok(KeyAlgorithm::ES512),
222225
"RS256" => Ok(KeyAlgorithm::RS256),
223226
"RS384" => Ok(KeyAlgorithm::RS384),
224227
"PS256" => Ok(KeyAlgorithm::PS256),
@@ -553,6 +556,7 @@ impl Jwk {
553556
Algorithm::HS512 => KeyAlgorithm::HS512,
554557
Algorithm::ES256 => KeyAlgorithm::ES256,
555558
Algorithm::ES384 => KeyAlgorithm::ES384,
559+
Algorithm::ES512 => KeyAlgorithm::ES512,
556560
Algorithm::RS256 => KeyAlgorithm::RS256,
557561
Algorithm::RS384 => KeyAlgorithm::RS384,
558562
Algorithm::RS512 => KeyAlgorithm::RS512,

0 commit comments

Comments
 (0)