1#![cfg_attr(docsrs, feature(doc_auto_cfg))]
104pub mod error;
105pub use base64::DecodeError as Base64DecodeError;
106use base64::Engine;
107pub use error::Error;
108use serde::{Deserialize, Serialize};
109use ssi_claims_core::{
110 ProofValidationError, ResolverProvider, ValidateClaims, VerifiableClaims, Verification,
111};
112use ssi_jwk::{Algorithm, Base64urlUInt, JWKResolver, Params as JWKParams, JWK};
113use std::{borrow::Cow, collections::BTreeMap};
114
115pub type VerificationWarnings = Vec<String>;
116
117pub(crate) mod utils;
118
119mod compact;
120pub use compact::*;
121
122mod signature;
123pub use signature::*;
124
125mod verification;
126pub use verification::*;
127
128#[derive(Clone, PartialEq, Eq)]
130pub struct JwsParts<T = Vec<u8>> {
131 pub header: Header,
133
134 pub payload: T,
136
137 pub signature: JwsSignature,
139}
140
141impl<T> JwsParts<T> {
142 pub fn new(header: Header, payload: T, signature: JwsSignature) -> Self {
143 Self {
144 header,
145 payload,
146 signature,
147 }
148 }
149
150 pub fn map<U>(self, f: impl FnOnce(T) -> U) -> JwsParts<U> {
151 JwsParts {
152 header: self.header,
153 payload: f(self.payload),
154 signature: self.signature,
155 }
156 }
157
158 pub fn try_map<U, E>(self, f: impl FnOnce(T) -> Result<U, E>) -> Result<JwsParts<U>, E> {
159 Ok(JwsParts {
160 header: self.header,
161 payload: f(self.payload)?,
162 signature: self.signature,
163 })
164 }
165}
166
167impl<T: ?Sized + ToOwned> JwsParts<Cow<'_, T>> {
168 pub fn into_owned(self) -> JwsParts<T::Owned> {
169 JwsParts::new(self.header, self.payload.into_owned(), self.signature)
170 }
171}
172
173#[derive(Debug, Clone, PartialEq, Eq)]
177pub struct DecodedJws<'a, T = Vec<u8>> {
178 pub signing_bytes: DecodedSigningBytes<'a, T>,
179 pub signature: JwsSignature,
180}
181
182impl<'a, T> DecodedJws<'a, T> {
183 pub fn new(signing_bytes: DecodedSigningBytes<'a, T>, signature: JwsSignature) -> Self {
184 Self {
185 signing_bytes,
186 signature,
187 }
188 }
189
190 pub fn header(&self) -> &Header {
191 &self.signing_bytes.header
192 }
193
194 pub fn map<U>(self, f: impl FnOnce(T) -> U) -> DecodedJws<'a, U> {
195 DecodedJws::new(self.signing_bytes.map(f), self.signature)
196 }
197
198 pub fn try_map<U, E>(self, f: impl FnOnce(T) -> Result<U, E>) -> Result<DecodedJws<'a, U>, E> {
199 Ok(DecodedJws::new(
200 self.signing_bytes.try_map(f)?,
201 self.signature,
202 ))
203 }
204
205 pub fn into_jws(self) -> JwsParts<T> {
206 JwsParts::new(
207 self.signing_bytes.header,
208 self.signing_bytes.payload,
209 self.signature,
210 )
211 }
212
213 pub fn into_jws_and_signing_bytes(self) -> (JwsParts<T>, Cow<'a, [u8]>) {
214 (
215 JwsParts::new(
216 self.signing_bytes.header,
217 self.signing_bytes.payload,
218 self.signature,
219 ),
220 self.signing_bytes.bytes,
221 )
222 }
223
224 pub fn into_encoded(self) -> JwsVec {
225 JwsVec::from_signing_bytes_and_signature(
226 self.signing_bytes.bytes.into_owned(),
227 self.signature.encode().as_bytes(),
228 )
229 .unwrap()
230 }
231
232 pub async fn verify<P>(&self, params: P) -> Result<Verification, ProofValidationError>
257 where
258 T: ValidateJwsHeader<P> + ValidateClaims<P, JwsSignature>,
259 P: ResolverProvider,
260 P::Resolver: JWKResolver,
261 {
262 VerifiableClaims::verify(self, params).await
263 }
264}
265
266impl<T: ?Sized + ToOwned> DecodedJws<'_, &T> {
267 pub fn to_owned(&self) -> DecodedJws<'static, T::Owned> {
268 DecodedJws {
269 signing_bytes: self.signing_bytes.to_owned(),
270 signature: self.signature.to_owned(),
271 }
272 }
273}
274
275impl<T: ?Sized + ToOwned> DecodedJws<'_, Cow<'_, T>> {
276 pub fn into_owned(self) -> DecodedJws<'static, T::Owned> {
277 DecodedJws::new(self.signing_bytes.into_owned(), self.signature)
278 }
279}
280
281#[derive(Debug, Clone, PartialEq, Eq)]
283pub struct DecodedSigningBytes<'a, T = Vec<u8>> {
284 pub bytes: Cow<'a, [u8]>,
286
287 pub header: Header,
289
290 pub payload: T,
292}
293
294impl<'a, T> DecodedSigningBytes<'a, T> {
295 pub fn new(bytes: Cow<'a, [u8]>, header: Header, payload: T) -> Self {
296 Self {
297 bytes,
298 header,
299 payload,
300 }
301 }
302
303 pub fn map<U>(self, f: impl FnOnce(T) -> U) -> DecodedSigningBytes<'a, U> {
304 DecodedSigningBytes {
305 bytes: self.bytes,
306 header: self.header,
307 payload: f(self.payload),
308 }
309 }
310
311 pub fn try_map<U, E>(
312 self,
313 f: impl FnOnce(T) -> Result<U, E>,
314 ) -> Result<DecodedSigningBytes<'a, U>, E> {
315 Ok(DecodedSigningBytes {
316 bytes: self.bytes,
317 header: self.header,
318 payload: f(self.payload)?,
319 })
320 }
321}
322
323impl<T: ?Sized + ToOwned> DecodedSigningBytes<'_, &T> {
324 pub fn to_owned(&self) -> DecodedSigningBytes<'static, T::Owned> {
325 DecodedSigningBytes {
326 bytes: Cow::Owned(self.bytes.as_ref().to_owned()),
327 header: self.header.clone(),
328 payload: self.payload.to_owned(),
329 }
330 }
331}
332
333impl<T: ?Sized + ToOwned> DecodedSigningBytes<'_, Cow<'_, T>> {
334 pub fn into_owned(self) -> DecodedSigningBytes<'static, T::Owned> {
335 DecodedSigningBytes {
336 bytes: Cow::Owned(self.bytes.into_owned()),
337 header: self.header,
338 payload: self.payload.into_owned(),
339 }
340 }
341}
342
343#[derive(Debug, thiserror::Error)]
344pub enum DecodeError {
345 #[error("invalid header: {0}")]
346 Header(InvalidHeader),
347
348 #[error("invalid payload: {0}")]
349 Payload(Base64DecodeError),
350
351 #[error("invalid signature: {0}")]
352 Signature(Base64DecodeError),
353}
354
355#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Default)]
357pub struct Header {
358 #[serde(rename = "alg")]
359 pub algorithm: Algorithm,
360
361 #[serde(skip_serializing_if = "Option::is_none")]
362 #[serde(rename = "jku")]
363 pub jwk_set_url: Option<String>,
364
365 #[serde(skip_serializing_if = "Option::is_none")]
366 pub jwk: Option<JWK>,
367
368 #[serde(skip_serializing_if = "Option::is_none")]
369 #[serde(rename = "kid")]
370 pub key_id: Option<String>,
371
372 #[serde(skip_serializing_if = "Option::is_none")]
373 #[serde(rename = "x5u")]
374 pub x509_url: Option<String>,
375
376 #[serde(skip_serializing_if = "Option::is_none")]
377 #[serde(rename = "x5c")]
378 pub x509_certificate_chain: Option<Vec<String>>,
379
380 #[serde(skip_serializing_if = "Option::is_none")]
381 #[serde(rename = "x5t")]
382 pub x509_thumbprint_sha1: Option<Base64urlUInt>,
383
384 #[serde(skip_serializing_if = "Option::is_none")]
385 #[serde(rename = "x5t#S256")]
386 pub x509_thumbprint_sha256: Option<Base64urlUInt>,
387
388 #[serde(skip_serializing_if = "Option::is_none")]
389 #[serde(rename = "typ")]
390 pub type_: Option<String>,
391
392 #[serde(skip_serializing_if = "Option::is_none")]
393 #[serde(rename = "cty")]
394 pub content_type: Option<String>,
395
396 #[serde(skip_serializing_if = "Option::is_none")]
397 #[serde(rename = "crit")]
398 pub critical: Option<Vec<String>>,
399
400 #[serde(skip_serializing_if = "Option::is_none")]
401 #[serde(rename = "b64")]
402 pub base64urlencode_payload: Option<bool>,
403
404 #[serde(skip_serializing_if = "BTreeMap::is_empty")]
405 #[serde(flatten)]
406 pub additional_parameters: BTreeMap<String, serde_json::Value>,
407}
408
409#[derive(Debug, thiserror::Error)]
410pub enum InvalidHeader {
411 #[error(transparent)]
412 Base64(Base64DecodeError),
413
414 #[error(transparent)]
415 Json(serde_json::Error),
416}
417
418impl From<Base64DecodeError> for InvalidHeader {
419 fn from(value: Base64DecodeError) -> Self {
420 InvalidHeader::Base64(value)
421 }
422}
423
424impl From<serde_json::Error> for InvalidHeader {
425 fn from(value: serde_json::Error) -> Self {
426 InvalidHeader::Json(value)
427 }
428}
429
430impl Header {
431 pub fn new_unencoded(algorithm: Algorithm, key_id: Option<String>) -> Self {
439 Self {
440 algorithm,
441 key_id,
442 base64urlencode_payload: Some(false),
443 critical: Some(vec!["b64".to_string()]),
444 ..Default::default()
445 }
446 }
447
448 pub fn decode(base_64: &[u8]) -> Result<Self, InvalidHeader> {
450 let header_json = base64::prelude::BASE64_URL_SAFE_NO_PAD.decode(base_64)?;
451 Ok(serde_json::from_slice(&header_json)?)
452 }
453
454 pub fn to_json_string(&self) -> String {
455 serde_json::to_string(self).unwrap()
456 }
457
458 pub fn encode(&self) -> String {
459 base64::prelude::BASE64_URL_SAFE_NO_PAD.encode(self.to_json_string())
460 }
461
462 pub fn encode_signing_bytes(&self, payload: &[u8]) -> Vec<u8> {
463 let mut result = self.encode().into_bytes();
464 result.push(b'.');
465
466 if self.base64urlencode_payload.unwrap_or(true) {
467 let encoded_payload = base64::prelude::BASE64_URL_SAFE_NO_PAD.encode(payload);
468 result.extend(encoded_payload.into_bytes())
469 } else {
470 result.extend(payload)
471 }
472
473 result
474 }
475}
476
477fn base64_encode_json<T: Serialize>(object: &T) -> Result<String, Error> {
478 let json = serde_json::to_string(&object)?;
479 Ok(base64::prelude::BASE64_URL_SAFE_NO_PAD.encode(json))
480}
481
482#[allow(unreachable_code, unused_variables)]
483pub fn sign_bytes(algorithm: Algorithm, data: &[u8], key: &JWK) -> Result<Vec<u8>, Error> {
484 let signature = match &key.params {
485 #[cfg(all(feature = "rsa", feature = "ring"))]
486 JWKParams::RSA(rsa_params) => {
487 rsa_params.validate_key_size()?;
488 let key_pair = ring::signature::RsaKeyPair::try_from(rsa_params)?;
489 let padding_alg: &dyn ring::signature::RsaEncoding = match algorithm {
490 Algorithm::RS256 => &ring::signature::RSA_PKCS1_SHA256,
491 Algorithm::PS256 => &ring::signature::RSA_PSS_SHA256,
492 _ => return Err(Error::AlgorithmNotImplemented(algorithm.to_string())),
493 };
494 let mut sig = vec![0u8; key_pair.public_modulus_len()];
495 let rng = ring::rand::SystemRandom::new();
496 key_pair.sign(padding_alg, &rng, data, &mut sig)?;
497 sig
498 }
499 #[cfg(all(feature = "rsa", not(feature = "ring")))]
500 JWKParams::RSA(rsa_params) => {
501 rsa_params.validate_key_size()?;
502 let private_key = rsa::RsaPrivateKey::try_from(rsa_params)?;
503 let padding;
504 let hashed;
505 match algorithm {
506 Algorithm::RS256 => {
507 let hash = rsa::hash::Hash::SHA2_256;
508 padding = rsa::padding::PaddingScheme::new_pkcs1v15_sign(Some(hash));
509 hashed = ssi_crypto::hashes::sha256::sha256(data);
510 }
511 Algorithm::PS256 => {
512 let hash = rsa::hash::Hash::SHA2_256;
513 let rng = rand::rngs::OsRng {};
514 padding =
515 rsa::PaddingScheme::new_pss_with_salt::<sha2::Sha256, _>(rng, hash.size());
516 hashed = ssi_crypto::hashes::sha256::sha256(data);
517 }
518 _ => return Err(Error::AlgorithmNotImplemented(algorithm.to_string())),
519 }
520 private_key
521 .sign(padding, &hashed)
522 .map_err(ssi_jwk::Error::from)?
523 }
524 #[cfg(any(feature = "ring", feature = "ed25519"))]
525 JWKParams::OKP(okp) => {
526 use blake2::digest::{consts::U32, Digest};
527 if algorithm != Algorithm::EdDSA && algorithm != Algorithm::EdBlake2b {
528 return Err(Error::UnsupportedAlgorithm(algorithm.to_string()));
529 }
530 if okp.curve != *"Ed25519" {
531 return Err(ssi_jwk::Error::CurveNotImplemented(okp.curve.to_string()).into());
532 }
533 let hash = match algorithm {
534 Algorithm::EdBlake2b => blake2::Blake2b::<U32>::new_with_prefix(data)
535 .finalize()
536 .to_vec(),
537 _ => data.to_vec(),
538 };
539 #[cfg(feature = "ring")]
540 {
541 let key_pair = ring::signature::Ed25519KeyPair::try_from(okp)?;
542 key_pair.sign(&hash).as_ref().to_vec()
543 }
544 #[cfg(all(feature = "ed25519", not(feature = "ring")))]
546 {
547 let secret = ed25519_dalek::SigningKey::try_from(okp)?;
548 use ed25519_dalek::Signer;
549 secret.sign(&hash).to_bytes().to_vec()
550 }
551 }
552 #[allow(unused)]
553 JWKParams::EC(ec) => match algorithm {
554 #[cfg(feature = "secp384r1")]
555 Algorithm::ES384 => {
556 use p384::ecdsa::{signature::Signer, Signature};
557 let curve = ec.curve.as_ref().ok_or(ssi_jwk::Error::MissingCurve)?;
558 let secret_key = p384::SecretKey::try_from(ec)?;
559 let signing_key = p384::ecdsa::SigningKey::from(secret_key);
560 let sig: p384::ecdsa::Signature =
561 signing_key.try_sign(data).map_err(ssi_jwk::Error::from)?;
562 sig.to_bytes().to_vec()
563 }
564 #[cfg(feature = "secp256r1")]
565 Algorithm::ES256 => {
566 use p256::ecdsa::{signature::Signer, Signature};
567 let curve = ec.curve.as_ref().ok_or(ssi_jwk::Error::MissingCurve)?;
568 let secret_key = p256::SecretKey::try_from(ec)?;
569 let signing_key = p256::ecdsa::SigningKey::from(secret_key);
570 let sig: p256::ecdsa::Signature =
571 signing_key.try_sign(data).map_err(ssi_jwk::Error::from)?; sig.to_bytes().to_vec()
573 }
574 #[cfg(feature = "secp256k1")]
575 Algorithm::ES256K => {
576 use k256::ecdsa::{signature::Signer, Signature};
577 let curve = ec.curve.as_ref().ok_or(ssi_jwk::Error::MissingCurve)?;
578 let secret_key = k256::SecretKey::try_from(ec)?;
579 let signing_key = k256::ecdsa::SigningKey::from(secret_key);
580 let sig: Signature = signing_key.try_sign(data).map_err(ssi_jwk::Error::from)?; sig.to_bytes().to_vec()
582 }
583 #[cfg(feature = "secp256k1")]
584 Algorithm::ES256KR => {
585 use k256::ecdsa::{
586 signature::{digest::Digest, Signer},
587 Signature,
588 };
589 let curve = ec.curve.as_ref().ok_or(Error::MissingCurve)?;
590 let secret_key = k256::SecretKey::try_from(ec)?;
591 let signing_key = k256::ecdsa::SigningKey::from(secret_key);
592 let (sig, rec_id) =
596 signing_key.sign_digest_recoverable(sha2::Sha256::new_with_prefix(data))?;
597 let mut res = sig.to_bytes().to_vec();
598 res.push(rec_id.to_byte());
599 res
600 }
601 #[cfg(feature = "secp256k1")]
602 Algorithm::ESKeccakKR => {
603 use k256::ecdsa::{
604 signature::{digest::Digest, Signer},
605 Signature,
606 };
607 let curve = ec.curve.as_ref().ok_or(ssi_jwk::Error::MissingCurve)?;
608 let secret_key = k256::SecretKey::try_from(ec)?;
609 let signing_key = k256::ecdsa::SigningKey::from(secret_key);
610 let (sig, rec_id) = signing_key
614 .sign_digest_recoverable(sha3::Keccak256::new_with_prefix(data))
615 .map_err(ssi_jwk::Error::from)?;
616 let mut res = sig.to_bytes().to_vec();
617 res.push(rec_id.to_byte());
618 res
619 }
620 #[cfg(feature = "secp256r1")]
621 Algorithm::ESBlake2b => {
622 use p256::ecdsa::{
623 signature::{
624 digest::{consts::U32, Digest},
625 DigestSigner,
626 },
627 Signature,
628 };
629 let curve = ec.curve.as_ref().ok_or(Error::MissingCurve)?;
630 let secret_key = p256::SecretKey::try_from(ec)?;
631 let signing_key = p256::ecdsa::SigningKey::from(secret_key);
632 let sig: p256::ecdsa::Signature =
633 signing_key.try_sign_digest(blake2::Blake2b::<U32>::new_with_prefix(data))?;
634 sig.to_bytes().to_vec()
635 }
636 #[cfg(feature = "secp256k1")]
637 Algorithm::ESBlake2bK => {
638 use k256::ecdsa::{
639 signature::{
640 digest::{consts::U32, Digest},
641 DigestSigner,
642 },
643 Signature,
644 };
645 let curve = ec.curve.as_ref().ok_or(Error::MissingCurve)?;
646 let secret_key = k256::SecretKey::try_from(ec)?;
647 let signing_key = k256::ecdsa::SigningKey::from(secret_key);
648 let sig: k256::ecdsa::Signature =
649 signing_key.try_sign_digest(blake2::Blake2b::<U32>::new_with_prefix(data))?;
650 sig.to_bytes().to_vec()
651 }
652 _ => {
653 return Err(Error::UnsupportedAlgorithm(algorithm.to_string()));
654 }
655 },
656 _ => {
657 return Err(Error::Jwk(ssi_jwk::Error::KeyTypeNotImplemented(Box::new(
658 key.to_public(),
659 ))))
660 }
661 };
662 clear_on_drop::clear_stack(1);
663 Ok(signature)
664}
665
666pub fn sign_bytes_b64(algorithm: Algorithm, data: &[u8], key: &JWK) -> Result<String, Error> {
667 let signature = sign_bytes(algorithm, data, key)?;
668 let sig_b64 = base64::prelude::BASE64_URL_SAFE_NO_PAD.encode(signature);
669 Ok(sig_b64)
670}
671
672#[allow(unreachable_code, unused_variables, unused_mut)]
673pub fn verify_bytes_warnable(
674 algorithm: Algorithm,
675 data: &[u8],
676 key: &JWK,
677 signature: &[u8],
678) -> Result<VerificationWarnings, Error> {
679 let mut warnings = VerificationWarnings::default();
680 if let Some(key_algorithm) = key.algorithm {
681 if key_algorithm != algorithm
682 && !(key_algorithm == Algorithm::EdDSA && algorithm == Algorithm::EdBlake2b)
683 && !(key_algorithm == Algorithm::ES256 && algorithm == Algorithm::ESBlake2b)
684 && !(key_algorithm == Algorithm::ES256K && algorithm == Algorithm::ESBlake2bK)
685 && !(key_algorithm == Algorithm::ES256KR && algorithm == Algorithm::ESBlake2bK)
686 {
687 return Err(Error::AlgorithmMismatch);
688 }
689 }
690 match &key.params {
691 #[cfg(all(feature = "rsa", feature = "ring"))]
692 JWKParams::RSA(rsa_params) => {
693 rsa_params.validate_key_size()?;
694 use ring::signature::RsaPublicKeyComponents;
695 let public_key = RsaPublicKeyComponents::try_from(rsa_params)?;
696 let parameters = match algorithm {
697 Algorithm::RS256 => &ring::signature::RSA_PKCS1_2048_8192_SHA256,
698 Algorithm::PS256 => &ring::signature::RSA_PSS_2048_8192_SHA256,
699 _ => return Err(Error::AlgorithmNotImplemented(algorithm.to_string())),
700 };
701 public_key.verify(parameters, data, signature)?
702 }
703 #[cfg(all(feature = "rsa", not(feature = "ring")))]
704 JWKParams::RSA(rsa_params) => {
705 rsa_params.validate_key_size()?;
706 use rsa::PublicKey;
707 let public_key = rsa::RsaPublicKey::try_from(rsa_params)?;
708 let padding;
709 let hashed;
710 match algorithm {
711 Algorithm::RS256 => {
712 let hash = rsa::hash::Hash::SHA2_256;
713 padding = rsa::padding::PaddingScheme::new_pkcs1v15_sign(Some(hash));
714 hashed = ssi_crypto::hashes::sha256::sha256(data);
715 }
716 Algorithm::PS256 => {
717 let rng = rand::rngs::OsRng {};
718 padding = rsa::PaddingScheme::new_pss::<sha2::Sha256, _>(rng);
719 hashed = ssi_crypto::hashes::sha256::sha256(data);
720 }
721 _ => return Err(Error::AlgorithmNotImplemented(algorithm.to_string())),
722 }
723 public_key
724 .verify(padding, &hashed, signature)
725 .map_err(ssi_jwk::Error::from)?;
726 }
727 #[cfg(any(feature = "ring", feature = "ed25519"))]
729 JWKParams::OKP(okp) => {
730 use blake2::digest::{consts::U32, Digest};
731 if okp.curve != *"Ed25519" {
732 return Err(ssi_jwk::Error::CurveNotImplemented(okp.curve.to_string()).into());
733 }
734 let hash = match algorithm {
735 Algorithm::EdBlake2b => <blake2::Blake2b<U32> as Digest>::new_with_prefix(data)
736 .finalize()
737 .to_vec(),
738 _ => data.to_vec(),
739 };
740 #[cfg(feature = "ring")]
741 {
742 use ring::signature::UnparsedPublicKey;
743 let verification_algorithm = &ring::signature::ED25519;
744 let public_key = UnparsedPublicKey::new(verification_algorithm, &okp.public_key.0);
745 public_key.verify(&hash, signature)?;
746 }
747 #[cfg(feature = "ed25519")]
748 {
749 use ed25519_dalek::Verifier;
750 let public_key = ed25519_dalek::VerifyingKey::try_from(okp)?;
751 let signature: ed25519_dalek::Signature =
752 signature.try_into().map_err(ssi_jwk::Error::from)?;
753 public_key
754 .verify(&hash, &signature)
755 .map_err(ssi_jwk::Error::from)?;
756 }
757 }
758 #[allow(unused)]
759 JWKParams::EC(ec) => match algorithm {
760 #[cfg(feature = "secp256r1")]
761 Algorithm::ES256 => {
762 use p256::ecdsa::signature::Verifier;
763 let curve = ec.curve.as_ref().ok_or(ssi_jwk::Error::MissingCurve)?;
764 let public_key = p256::PublicKey::try_from(ec)?;
765 let verifying_key = p256::ecdsa::VerifyingKey::from(public_key);
766 let sig =
767 p256::ecdsa::Signature::try_from(signature).map_err(ssi_jwk::Error::from)?;
768 verifying_key
769 .verify(data, &sig)
770 .map_err(ssi_jwk::Error::from)?;
771 }
772 #[cfg(feature = "secp256k1")]
773 Algorithm::ES256K => {
774 use k256::ecdsa::signature::Verifier;
775 let curve = ec.curve.as_ref().ok_or(ssi_jwk::Error::MissingCurve)?;
776 let public_key = k256::PublicKey::try_from(ec)?;
777 let verifying_key = k256::ecdsa::VerifyingKey::from(public_key);
778 let sig =
779 k256::ecdsa::Signature::try_from(signature).map_err(ssi_jwk::Error::from)?;
780 let normalized_sig = if let Some(s) = sig.normalize_s() {
781 let sig_normalized_b64 =
783 base64::prelude::BASE64_URL_SAFE_NO_PAD.encode(s.to_bytes());
784 warnings.push(format!(
785 "Non-normalized ES256K signature. Normalized: {sig_normalized_b64}"
786 ));
787 s
788 } else {
789 sig
790 };
791 verifying_key
792 .verify(data, &normalized_sig)
793 .map_err(ssi_jwk::Error::from)?;
794 }
795 #[cfg(feature = "secp256k1")]
796 Algorithm::ES256KR => {
797 use k256::ecdsa::{
798 signature::{
799 digest::{consts::U32, Digest},
800 DigestVerifier, Verifier,
801 },
802 RecoveryId, VerifyingKey,
803 };
804 if signature.len() != 65 {
805 Err(k256::ecdsa::Error::new())?;
806 }
807 let curve = ec.curve.as_ref().ok_or(ssi_jwk::Error::MissingCurve)?;
808 let public_key = k256::PublicKey::try_from(ec)?;
809 let verifying_key = k256::ecdsa::VerifyingKey::from(public_key);
810 let sig = k256::ecdsa::Signature::try_from(&signature[..64])
811 .map_err(ssi_jwk::Error::from)?;
812 let rec_id = k256::ecdsa::RecoveryId::try_from(signature[64])
813 .map_err(ssi_jwk::Error::from)?;
814 match VerifyingKey::recover_from_digest(
815 <sha2::Sha256 as Digest>::new_with_prefix(data),
816 &sig,
817 rec_id,
818 ) {
819 Err(_e) => {
820 verify_bytes(Algorithm::ESKeccakKR, data, key, signature)?;
822 warnings.push(
823 "Signature uses legacy mode ES256K-R with Keccak-256".to_string(),
824 );
825 }
826 Ok(recovered_key) => match recovered_key == verifying_key {
827 true => (),
828 false => Err(k256::ecdsa::Error::new())?,
829 },
830 }
831 }
832 #[cfg(feature = "eip")]
833 Algorithm::ESKeccakKR => {
834 use k256::ecdsa::{
835 signature::{
836 digest::{consts::U32, Digest},
837 DigestVerifier, Verifier,
838 },
839 RecoveryId, VerifyingKey,
840 };
841 if signature.len() != 65 {
842 Err(k256::ecdsa::Error::new())?;
843 }
844 let curve = ec.curve.as_ref().ok_or(ssi_jwk::Error::MissingCurve)?;
845 let public_key = k256::PublicKey::try_from(ec)?;
846 let verifying_key = k256::ecdsa::VerifyingKey::from(public_key);
847 let sig = k256::ecdsa::Signature::try_from(&signature[..64])
848 .map_err(ssi_jwk::Error::from)?;
849 let rec_id = k256::ecdsa::RecoveryId::try_from(signature[64])
850 .map_err(ssi_jwk::Error::from)?;
851 let recovered_key = VerifyingKey::recover_from_digest(
852 sha3::Keccak256::new_with_prefix(data),
853 &sig,
854 rec_id,
855 )
856 .map_err(ssi_jwk::Error::from)?;
857 match recovered_key == verifying_key {
858 true => (),
859 false => Err(k256::ecdsa::Error::new())?,
860 }
861 }
862 #[cfg(feature = "secp256r1")]
863 Algorithm::ESBlake2b => {
864 use p256::ecdsa::{
865 signature::{
866 digest::{consts::U32, Digest},
867 DigestVerifier,
868 },
869 Signature,
870 };
871 let curve = ec.curve.as_ref().ok_or(ssi_jwk::Error::MissingCurve)?;
872 let public_key = p256::PublicKey::try_from(ec)?;
873 let verifying_key = p256::ecdsa::VerifyingKey::from(public_key);
874 let sig =
875 p256::ecdsa::Signature::try_from(signature).map_err(ssi_jwk::Error::from)?;
876 verifying_key
877 .verify_digest(
878 <blake2::Blake2b<U32> as Digest>::new_with_prefix(data),
879 &sig,
880 )
881 .map_err(ssi_jwk::Error::from)?;
882 }
883 #[cfg(feature = "secp256k1")]
884 Algorithm::ESBlake2bK => {
885 use k256::ecdsa::signature::{
886 digest::{consts::U32, Digest},
887 DigestVerifier,
888 };
889 let curve = ec.curve.as_ref().ok_or(ssi_jwk::Error::MissingCurve)?;
890 let public_key = k256::PublicKey::try_from(ec)?;
891 let verifying_key = k256::ecdsa::VerifyingKey::from(public_key);
892 let sig =
893 k256::ecdsa::Signature::try_from(signature).map_err(ssi_jwk::Error::from)?;
894 verifying_key
895 .verify_digest(
896 <blake2::Blake2b<U32> as Digest>::new_with_prefix(data),
897 &sig,
898 )
899 .map_err(ssi_jwk::Error::from)?;
900 }
901 #[cfg(feature = "secp384r1")]
902 Algorithm::ES384 => {
903 use p384::ecdsa::signature::Verifier;
904 let curve = ec.curve.as_ref().ok_or(ssi_jwk::Error::MissingCurve)?;
905 let public_key = p384::PublicKey::try_from(ec)?;
906 let verifying_key = p384::ecdsa::VerifyingKey::from(public_key);
907 let sig =
908 p384::ecdsa::Signature::try_from(signature).map_err(ssi_jwk::Error::from)?;
909 verifying_key
910 .verify(data, &sig)
911 .map_err(ssi_jwk::Error::from)?;
912 }
913 _ => {
914 return Err(Error::UnsupportedAlgorithm(algorithm.to_string()));
915 }
916 },
917 _ => {
918 return Err(Error::Jwk(ssi_jwk::Error::KeyTypeNotImplemented(Box::new(
919 key.to_public(),
920 ))))
921 }
922 }
923 Ok(warnings)
924}
925
926pub fn verify_bytes(
927 algorithm: Algorithm,
928 data: &[u8],
929 key: &JWK,
930 signature: &[u8],
931) -> Result<(), Error> {
932 verify_bytes_warnable(algorithm, data, key, signature)?;
933 Ok(())
934}
935
936pub fn recover(algorithm: Algorithm, data: &[u8], signature: &[u8]) -> Result<JWK, Error> {
939 match algorithm {
940 #[cfg(feature = "secp256k1")]
941 Algorithm::ES256KR => {
942 use k256::ecdsa::VerifyingKey;
943 if signature.len() != 65 {
944 Err(k256::ecdsa::Error::new())?;
945 }
946 let sig =
947 k256::ecdsa::Signature::try_from(&signature[..64]).map_err(ssi_jwk::Error::from)?;
948 let rec_id =
949 k256::ecdsa::RecoveryId::try_from(signature[64]).map_err(ssi_jwk::Error::from)?;
950 let hash = ssi_crypto::hashes::sha256::sha256(data);
951 let digest = k256::elliptic_curve::FieldBytes::<k256::Secp256k1>::from_slice(&hash);
952 let recovered_key = VerifyingKey::recover_from_prehash(digest, &sig, rec_id)
953 .map_err(ssi_jwk::Error::from)?;
954 use ssi_jwk::ECParams;
955 let jwk = JWK {
956 params: JWKParams::EC(ECParams::from(
957 &k256::PublicKey::from_sec1_bytes(&recovered_key.to_sec1_bytes())
958 .map_err(ssi_jwk::Error::from)?,
959 )),
960 public_key_use: None,
961 key_operations: None,
962 algorithm: None,
963 key_id: None,
964 x509_url: None,
965 x509_certificate_chain: None,
966 x509_thumbprint_sha1: None,
967 x509_thumbprint_sha256: None,
968 };
969 Ok(jwk)
970 }
971 #[cfg(feature = "secp256k1")]
972 Algorithm::ESKeccakKR => {
973 use k256::ecdsa::{signature::digest::Digest, VerifyingKey};
974 if signature.len() != 65 {
975 Err(k256::ecdsa::Error::new())?;
976 }
977 let sig =
978 k256::ecdsa::Signature::try_from(&signature[..64]).map_err(ssi_jwk::Error::from)?;
979 let rec_id =
980 k256::ecdsa::RecoveryId::try_from(signature[64]).map_err(ssi_jwk::Error::from)?;
981 let recovered_key = VerifyingKey::recover_from_digest(
982 sha3::Keccak256::new_with_prefix(data),
983 &sig,
984 rec_id,
985 )
986 .map_err(ssi_jwk::Error::from)?;
987 use ssi_jwk::ECParams;
988 let jwk = JWK::from(JWKParams::EC(ECParams::from(
989 &k256::PublicKey::from_sec1_bytes(&recovered_key.to_sec1_bytes())
990 .map_err(ssi_jwk::Error::from)?,
991 )));
992 Ok(jwk)
993 }
994 _ => {
995 let _ = data;
996 let _ = signature;
997 Err(Error::UnsupportedAlgorithm(algorithm.to_string()))
998 }
999 }
1000}
1001
1002pub fn detached_sign_unencoded_payload(
1003 algorithm: Algorithm,
1004 payload: &[u8],
1005 key: &JWK,
1006) -> Result<String, Error> {
1007 let header = Header {
1008 algorithm,
1009 key_id: key.key_id.clone(),
1010 critical: Some(vec!["b64".to_string()]),
1011 base64urlencode_payload: Some(false),
1012 ..Default::default()
1013 };
1014 let header_b64 = base64_encode_json(&header)?;
1015 let signing_input = [header_b64.as_bytes(), b".", payload].concat();
1016 let sig_b64 = sign_bytes_b64(header.algorithm, &signing_input, key)?;
1017 let jws = header_b64 + ".." + &sig_b64;
1018 Ok(jws)
1019}
1020
1021pub fn prepare_detached_unencoded_payload(
1022 algorithm: Algorithm,
1023 payload: &[u8],
1024) -> Result<(Header, Vec<u8>), Error> {
1025 let header = Header {
1026 algorithm,
1027 critical: Some(vec!["b64".to_string()]),
1028 base64urlencode_payload: Some(false),
1029 ..Default::default()
1030 };
1031 let header_b64 = base64_encode_json(&header)?;
1032 let signing_input = [header_b64.as_bytes(), b".", payload].concat().to_vec();
1033 Ok((header, signing_input))
1034}
1035
1036pub fn complete_sign_unencoded_payload(header: &Header, sig_b64: &str) -> Result<String, Error> {
1037 let header_b64 = base64_encode_json(header)?;
1038 let jws = header_b64 + ".." + sig_b64;
1039 Ok(jws)
1040}
1041
1042pub fn encode_sign(algorithm: Algorithm, payload: &str, key: &JWK) -> Result<String, Error> {
1043 let header = Header {
1044 algorithm,
1045 key_id: key.key_id.clone(),
1046 ..Default::default()
1047 };
1048 encode_sign_custom_header(payload, key, &header)
1049}
1050
1051pub fn encode_sign_custom_header(
1052 payload: &str,
1053 key: &JWK,
1054 header: &Header,
1055) -> Result<String, Error> {
1056 let header_b64 = base64_encode_json(header)?;
1057 let payload_b64 = base64::prelude::BASE64_URL_SAFE_NO_PAD.encode(payload);
1058 let signing_input = header_b64 + "." + &payload_b64;
1059 let sig_b64 = sign_bytes_b64(header.algorithm, signing_input.as_bytes(), key)?;
1060 let jws = [signing_input, sig_b64].join(".");
1061 Ok(jws)
1062}
1063
1064pub fn encode_unsigned(payload: &str) -> Result<String, Error> {
1065 let header = Header {
1066 algorithm: Algorithm::None,
1067 ..Default::default()
1068 };
1069 let header_b64 = base64_encode_json(&header)?;
1070 let payload_b64 = base64::prelude::BASE64_URL_SAFE_NO_PAD.encode(payload);
1071 Ok(header_b64 + "." + &payload_b64 + ".")
1072}
1073
1074pub fn split_jws(jws: &str) -> Result<(&str, &str, &str), Error> {
1075 let mut parts = jws.splitn(3, '.');
1076 Ok(
1077 match (parts.next(), parts.next(), parts.next(), parts.next()) {
1078 (Some(a), Some(b), Some(c), None) => (a, b, c),
1079 _ => return Err(Error::InvalidJws),
1080 },
1081 )
1082}
1083
1084pub fn split_detached_jws(jws: &str) -> Result<(&str, &str), Error> {
1085 let (header_b64, omitted_payload, signature_b64) = split_jws(jws)?;
1086 if !omitted_payload.is_empty() {
1087 return Err(Error::InvalidJws);
1088 }
1089 Ok((header_b64, signature_b64))
1090}
1091
1092pub fn decode_jws_parts(
1096 header_b64: &str,
1097 payload_enc: &[u8],
1098 signature_b64: &str,
1099) -> Result<DecodedJws<'static>, Error> {
1100 let signature = base64::prelude::BASE64_URL_SAFE_NO_PAD.decode(signature_b64)?;
1101 let header = Header::decode(header_b64.as_bytes())?;
1102 let payload = if header.base64urlencode_payload.unwrap_or(true) {
1103 base64::prelude::BASE64_URL_SAFE_NO_PAD.decode(payload_enc)?
1104 } else {
1105 payload_enc.to_vec()
1106 };
1107 for name in header.critical.iter().flatten() {
1108 match name.as_str() {
1109 "alg" | "jku" | "jwk" | "kid" | "x5u" | "x5c" | "x5t" | "x5t#S256" | "typ" | "cty"
1110 | "crit" => return Err(Error::InvalidCriticalHeader),
1111 "b64" => {}
1112 _ => return Err(Error::UnknownCriticalHeader),
1113 }
1114 }
1115 let signing_input = [header_b64.as_bytes(), b".", payload_enc].concat();
1116 Ok(DecodedJws::new(
1117 DecodedSigningBytes::new(Cow::Owned(signing_input), header, payload),
1118 signature.into(),
1119 ))
1120}
1121
1122pub fn detached_verify(jws: &str, payload_enc: &[u8], key: &JWK) -> Result<Header, Error> {
1124 let (header_b64, signature_b64) = split_detached_jws(jws)?;
1125 let (jws, signing_bytes) =
1126 decode_jws_parts(header_b64, payload_enc, signature_b64)?.into_jws_and_signing_bytes();
1127 verify_bytes(
1128 jws.header.algorithm,
1129 &signing_bytes,
1130 key,
1131 jws.signature.as_bytes(),
1132 )?;
1133 Ok(jws.header)
1134}
1135
1136pub fn detached_recover(jws: &str, payload_enc: &[u8]) -> Result<(Header, JWK), Error> {
1138 let (header_b64, signature_b64) = split_detached_jws(jws)?;
1139 let (jws, signing_bytes) =
1140 decode_jws_parts(header_b64, payload_enc, signature_b64)?.into_jws_and_signing_bytes();
1141 let key = recover(
1142 jws.header.algorithm,
1143 &signing_bytes,
1144 jws.signature.as_bytes(),
1145 )?;
1146 Ok((jws.header, key))
1147}
1148
1149pub fn detached_recover_legacy_keccak_es256kr(
1150 jws: &str,
1151 payload_enc: &[u8],
1152) -> Result<(Header, JWK), Error> {
1153 let (header_b64, signature_b64) = split_detached_jws(jws)?;
1154 let (mut jws, signing_bytes) =
1155 decode_jws_parts(header_b64, payload_enc, signature_b64)?.into_jws_and_signing_bytes();
1156 if jws.header.algorithm != Algorithm::ES256KR {
1158 return Err(Error::AlgorithmMismatch);
1159 }
1160 jws.header.algorithm = Algorithm::ESKeccakKR;
1161 let key = recover(
1162 jws.header.algorithm,
1163 &signing_bytes,
1164 jws.signature.as_bytes(),
1165 )?;
1166 Ok((jws.header, key))
1167}
1168
1169pub fn decode_verify(jws: &str, key: &JWK) -> Result<(Header, Vec<u8>), Error> {
1170 let (header_b64, payload_enc, signature_b64) = split_jws(jws)?;
1171 let (jws, signing_bytes) = decode_jws_parts(header_b64, payload_enc.as_bytes(), signature_b64)?
1172 .into_jws_and_signing_bytes();
1173 verify_bytes(
1174 jws.header.algorithm,
1175 &signing_bytes,
1176 key,
1177 jws.signature.as_bytes(),
1178 )?;
1179 Ok((jws.header, jws.payload))
1180}
1181
1182pub fn decode_unverified(jws: &str) -> Result<(Header, Vec<u8>), Error> {
1183 let (header_b64, payload_enc, signature_b64) = split_jws(jws)?;
1184 let jws = decode_jws_parts(header_b64, payload_enc.as_bytes(), signature_b64)?.into_jws();
1185 Ok((jws.header, jws.payload))
1186}
1187
1188#[cfg(test)]
1189mod tests {
1190 #[allow(unused_imports)]
1191 use super::*;
1192
1193 #[test]
1194 #[cfg(feature = "rsa")]
1195 fn jws_encode() {
1196 let payload =
1198 "{\"iss\":\"joe\",\r\n \"exp\":1300819380,\r\n \"http://example.com/is_root\":true}";
1199
1200 use serde_json::json;
1201 let key: JWK = serde_json::from_value(json!({"kty":"RSA",
1203 "n":"ofgWCuLjybRlzo0tZWJjNiuSfb4p4fAkd_wWJcyQoTbji9k0l8W26mPddxHmfHQp-Vaw-4qPCJrcS2mJPMEzP1Pt0Bm4d4QlL-yRT-SFd2lZS-pCgNMsD1W_YpRPEwOWvG6b32690r2jZ47soMZo9wGzjb_7OMg0LOL-bSf63kpaSHSXndS5z5rexMdbBYUsLA9e-KXBdQOS-UTo7WTBEMa2R2CapHg665xsmtdVMTBQY4uDZlxvb3qCo5ZwKh9kG4LT6_I5IhlJH7aGhyxXFvUK-DWNmoudF8NAco9_h9iaGNj8q2ethFkMLs91kzk2PAcDTW9gb54h4FRWyuXpoQ",
1204 "e":"AQAB",
1205 "d":"Eq5xpGnNCivDflJsRQBXHx1hdR1k6Ulwe2JZD50LpXyWPEAeP88vLNO97IjlA7_GQ5sLKMgvfTeXZx9SE-7YwVol2NXOoAJe46sui395IW_GO-pWJ1O0BkTGoVEn2bKVRUCgu-GjBVaYLU6f3l9kJfFNS3E0QbVdxzubSu3Mkqzjkn439X0M_V51gfpRLI9JYanrC4D4qAdGcopV_0ZHHzQlBjudU2QvXt4ehNYTCBr6XCLQUShb1juUO1ZdiYoFaFQT5Tw8bGUl_x_jTj3ccPDVZFD9pIuhLhBOneufuBiB4cS98l2SR_RQyGWSeWjnczT0QU91p1DhOVRuOopznQ",
1206 "p":"4BzEEOtIpmVdVEZNCqS7baC4crd0pqnRH_5IB3jw3bcxGn6QLvnEtfdUdiYrqBdss1l58BQ3KhooKeQTa9AB0Hw_Py5PJdTJNPY8cQn7ouZ2KKDcmnPGBY5t7yLc1QlQ5xHdwW1VhvKn-nXqhJTBgIPgtldC-KDV5z-y2XDwGUc", "q":"uQPEfgmVtjL0Uyyx88GZFF1fOunH3-7cepKmtH4pxhtCoHqpWmT8YAmZxaewHgHAjLYsp1ZSe7zFYHj7C6ul7TjeLQeZD_YwD66t62wDmpe_HlB-TnBA-njbglfIsRLtXlnDzQkv5dTltRJ11BKBBypeeF6689rjcJIDEz9RWdc",
1207 "dp":"BwKfV3Akq5_MFZDFZCnW-wzl-CCo83WoZvnLQwCTeDv8uzluRSnm71I3QCLdhrqE2e9YkxvuxdBfpT_PI7Yz-FOKnu1R6HsJeDCjn12Sk3vmAktV2zb34MCdy7cpdTh_YVr7tss2u6vneTwrA86rZtu5Mbr1C1XsmvkxHQAdYo0",
1208 "dq":"h_96-mK1R_7glhsum81dZxjTnYynPbZpHziZjeeHcXYsXaaMwkOlODsWa7I9xXDoRwbKgB719rrmI2oKr6N3Do9U0ajaHF-NKJnwgjMd2w9cjz3_-kyNlxAr2v4IKhGNpmM5iIgOS1VZnOZ68m6_pbLBSp3nssTdlqvd0tIiTHU",
1209 "qi":"IYd7DHOhrWvxkwPQsRM2tOgrjbcrfvtQJipd-DlcxyVuuM9sQLdgjVk2oy26F0EmpScGLq2MowX7fhd_QJQ3ydy5cY7YIBi87w93IKLEdfnbJtoOPLUW0ITrJReOgo1cq9SbsxYawBgfp_gh6A5603k2-ZQwVK0JKSHuLFkuQ3U"
1210 }))
1211 .unwrap();
1212
1213 let jws = encode_sign(Algorithm::RS256, payload, &key).unwrap();
1215 assert_eq!(jws, "eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.cC4hiUPoj9Eetdgtv3hF80EGrhuB__dzERat0XF9g2VtQgr9PJbu3XOiZj5RZmh7AAuHIm4Bh-0Qc_lF5YKt_O8W2Fp5jujGbds9uJdbF9CUAr7t1dnZcAcQjbKBYNX4BAynRFdiuB--f_nZLgrnbyTyWzO75vRK5h6xBArLIARNPvkSjtQBMHlb1L07Qe7K0GarZRmB_eSN9383LcOLn6_dO--xi12jzDwusC-eOkHWEsqtFZESc6BfI7noOPqvhJ1phCnvWh6IeYI2w9QOYEUipUTI8np6LbgGY9Fs98rqVt5AXLIhWkWywlVmtVrBp0igcN_IoypGlUPQGe77Rw");
1216
1217 decode_verify(&jws, &key).unwrap();
1218 }
1219
1220 #[test]
1221 #[cfg(feature = "secp256k1")]
1222 fn secp256k1_sign_verify() {
1223 let key = JWK::generate_secp256k1();
1224 let data = b"asdf";
1225 let bad_data = b"no";
1226 let sig = sign_bytes(Algorithm::ES256K, data, &key).unwrap();
1227 verify_bytes(Algorithm::ES256K, data, &key, &sig).unwrap();
1228 verify_bytes(Algorithm::ES256K, bad_data, &key, &sig).unwrap_err();
1229
1230 let key = JWK {
1232 algorithm: Some(Algorithm::ES256KR),
1233 ..key
1234 };
1235 verify_bytes(Algorithm::ES256KR, data, &key, &sig).unwrap_err();
1236 verify_bytes(Algorithm::ES256KR, bad_data, &key, &sig).unwrap_err();
1237
1238 let sig = sign_bytes(Algorithm::ES256KR, data, &key).unwrap();
1240 verify_bytes(Algorithm::ES256KR, data, &key, &sig).unwrap();
1241 verify_bytes(Algorithm::ES256KR, bad_data, &key, &sig).unwrap_err();
1242 let recovered_key = recover(Algorithm::ES256KR, data, &sig).unwrap();
1243 verify_bytes(Algorithm::ES256KR, data, &recovered_key, &sig).unwrap();
1244 let other_key = JWK::generate_secp256k1();
1245 verify_bytes(Algorithm::ES256KR, data, &other_key, &sig).unwrap_err();
1246 }
1247
1248 #[test]
1249 #[cfg(feature = "eip")]
1250 fn keccak_sign_verify() {
1251 let key = JWK::generate_secp256k1();
1252 let data = b"asdf";
1253 let bad_data = b"no";
1254 let key = JWK {
1256 algorithm: Some(Algorithm::ESKeccakKR),
1257 ..key
1258 };
1259
1260 let sig = sign_bytes(Algorithm::ES256KR, data, &key).unwrap();
1261 let other_key = JWK::generate_secp256k1();
1262 verify_bytes(Algorithm::ESKeccakKR, data, &key, &sig).unwrap_err();
1264 verify_bytes(Algorithm::ESKeccakKR, bad_data, &key, &sig).unwrap_err();
1265
1266 let sig = sign_bytes(Algorithm::ESKeccakKR, data, &key).unwrap();
1268 verify_bytes(Algorithm::ESKeccakKR, data, &key, &sig).unwrap();
1269 verify_bytes(Algorithm::ESKeccakKR, bad_data, &key, &sig).unwrap_err();
1270 let recovered_key = recover(Algorithm::ESKeccakKR, data, &sig).unwrap();
1271 verify_bytes(Algorithm::ESKeccakKR, data, &recovered_key, &sig).unwrap();
1272 verify_bytes(Algorithm::ESKeccakKR, data, &other_key, &sig).unwrap_err();
1273 }
1274
1275 #[test]
1276 #[cfg(feature = "secp256r1")]
1277 fn p256_sign_verify() {
1278 let key = JWK::generate_p256();
1279 let data = b"asdf";
1280 let bad_data = b"no";
1281 let sig = sign_bytes(Algorithm::ES256, data, &key).unwrap();
1282 verify_bytes(Algorithm::ES256, data, &key, &sig).unwrap();
1283 verify_bytes(Algorithm::ES256, bad_data, &key, &sig).unwrap_err();
1284
1285 let key: JWK = serde_json::from_str(include_str!(
1286 "../../../../../tests/secp256r1-2021-03-18.json"
1287 ))
1288 .unwrap();
1289 let payload = "{\"iss\":\"did:example:foo\",\"vp\":{\"@context\":[\"https://www.w3.org/2018/credentials/v1\"],\"type\":\"VerifiablePresentation\"}}";
1290 let jws = encode_sign(Algorithm::ES256, payload, &key).unwrap();
1291 assert_eq!(jws, "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJkaWQ6ZXhhbXBsZTpmb28iLCJ2cCI6eyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSJdLCJ0eXBlIjoiVmVyaWZpYWJsZVByZXNlbnRhdGlvbiJ9fQ.rJzO6MmTNS8Tn-L3baIf9_2Jr9OoK8E06MxJtofz8xMUGSom6eRUmWGZ7oQVjgP3HogOD80miTvuvKTWa54Nvw");
1292 decode_verify(&jws, &key).unwrap();
1293 }
1294
1295 #[test]
1296 #[cfg(feature = "secp384r1")]
1297 fn p384_sign_verify() {
1298 let key = JWK::generate_p384();
1299 let data = b"asdf";
1300 let bad_data = b"no";
1301 let sig = sign_bytes(Algorithm::ES384, data, &key).unwrap();
1302 verify_bytes(Algorithm::ES384, data, &key, &sig).unwrap();
1303 verify_bytes(Algorithm::ES384, bad_data, &key, &sig).unwrap_err();
1304
1305 let key: JWK = serde_json::from_str(include_str!(
1306 "../../../../../tests/secp384r1-2022-05-10.json"
1307 ))
1308 .unwrap();
1309 let payload = "{\"iss\":\"did:example:foo\",\"vp\":{\"@context\":[\"https://www.w3.org/2018/credentials/v1\"],\"type\":\"VerifiablePresentation\"}}";
1310 let jws = encode_sign(Algorithm::ES384, payload, &key).unwrap();
1311 dbg!(&jws);
1312 decode_verify(&jws, &key).unwrap();
1313
1314 const JWS: &str = "eyJhbGciOiJFUzM4NCJ9.eyJpc3MiOiJkaWQ6ZXhhbXBsZTpmb28iLCJ2cCI6eyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSJdLCJ0eXBlIjoiVmVyaWZpYWJsZVByZXNlbnRhdGlvbiJ9fQ.2vpBSFN7DxuS57epgq_e7-NyNiJ5eOOrExmi65C_wtZOC2-9i6fVvMnfUig7QmgiirznAg1wr_b7_kH-bbMCI5Pdf8pAnxQg3LL9I9OhzttyG06qAl9L7BE6aNS-aqnf";
1315 decode_verify(JWS, &key).unwrap();
1316 }
1317}