Skip to content

Commit

Permalink
Add (de)serialization support for OKP key type (#125)
Browse files Browse the repository at this point in the history
* add (de)serialization support for OKP JWK key type

* plugin_as_library lint has been removed

* run clippy, fmt checks only on stable

* Error::description is deprecated, use Display instead
  • Loading branch information
akhilles authored and lawliet89 committed Jan 7, 2020
1 parent a5b7393 commit 6162415
Show file tree
Hide file tree
Showing 8 changed files with 218 additions and 158 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ jobs:
with:
command: clippy
args: --all-targets --all-features -- -D warnings
if: matrix.rust == 'stable' && matrix.os == 'ubuntu-latest'

- uses: actions-rs/cargo@v1
name: Build
Expand All @@ -56,6 +57,7 @@ jobs:
with:
command: fmt
args: --all -- --check
if: matrix.rust == 'stable' && matrix.os == 'ubuntu-latest'

- uses: actions-rs/cargo@v1
name: Build Documentation
Expand Down
2 changes: 1 addition & 1 deletion doc/supported.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ for their use with the various algorithms is listed in the relevant section on t
| `EC` || |
| `RSA` || |
| `oct` || |
| `OKP` | | |
| `OKP` | | |

### JWK Parameters for Elliptic Curve Keys

Expand Down
125 changes: 38 additions & 87 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,47 +134,6 @@ impl From<string::FromUtf8Error> for Error {
}
}

impl error::Error for Error {
fn description(&self) -> &str {
use crate::Error::*;

match *self {
GenericError(ref err) => err,
JsonError(ref err) => err.description(),
DecodeBase64(ref err) => err.description(),
Utf8(ref err) => err.description(),
ValidationError(ref err) => err.description(),
DecodeError(ref err) => err.description(),
IOError(ref err) => err.description(),
UriParseError(ref err) => err.description(),
KeyRejected(ref err) => err.description_(),
WrongKeyType { .. } => {
"The wrong type of key was provided for the cryptographic operation"
}
WrongEncryptionOptions { .. } => {
"Wrong variant of `EncryptionOptions` was provided for the encryption operation"
}
UnspecifiedCryptographicError => "An Unspecified Cryptographic Error",
UnsupportedOperation => "This operation is not supported",
}
}

fn cause(&self) -> Option<&dyn error::Error> {
use crate::Error::*;

Some(match *self {
JsonError(ref err) => err,
DecodeBase64(ref err) => err,
Utf8(ref err) => err,
DecodeError(ref err) => err,
ValidationError(ref err) => err,
IOError(ref err) => err,
UriParseError(ref err) => err,
ref err => err,
})
}
}

impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use crate::Error::*;
Expand Down Expand Up @@ -205,53 +164,53 @@ impl fmt::Display for Error {
"{} was expected for this cryptographic operation but {} was provided",
expected, actual
),
UnspecifiedCryptographicError => write!(f, "{}", error::Error::description(self)),
UnsupportedOperation => write!(f, "{}", error::Error::description(self)),
UnspecifiedCryptographicError => write!(f, "An unspecified cryptographic error"),
UnsupportedOperation => write!(f, "This operation is not supported"),
}
}
}

impl error::Error for ValidationError {
fn description(&self) -> &str {
use crate::ValidationError::*;
impl error::Error for Error {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
use crate::Error::*;

match *self {
InvalidSignature => "Invalid Signature",
WrongAlgorithmHeader => {
"Token provided was signed or encrypted with an unexpected algorithm"
}
MissingRequiredClaims(_) => "Missing required claim",
Expired(_) => "Token expired",
NotYetValid(_) => "Token not yet valid",
TooOld(_) => "Token is too old",
InvalidIssuer(_) => "Issuer is invalid",
InvalidAudience(_) => "Audience of token is invalid",
KidMissing => "Header is missing Kid",
KeyNotFound => "Key not found in JWKS",
UnsupportedKeyAlgorithm => "Algorithm of JWK not supported",
JsonError(ref err) => Some(err),
DecodeBase64(ref err) => Some(err),
Utf8(ref err) => Some(err),
DecodeError(ref err) => Some(err),
ValidationError(ref err) => Some(err),
IOError(ref err) => Some(err),
UriParseError(ref err) => Some(err),
_ => None,
}
}

fn cause(&self) -> Option<&dyn error::Error> {
Some(self)
}
}

impl error::Error for DecodeError {
fn description(&self) -> &str {
impl fmt::Display for DecodeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use self::DecodeError::*;

match *self {
InvalidToken => "Invalid Token",
PartsLengthError { .. } => "Unexpected number of parts in compact JSON representation",
InvalidToken => write!(f, "Invalid token"),
PartsLengthError { expected, actual } => write!(
f,
"Expected {} parts in Compact JSON representation but got {}",
expected, actual
),
}
}
}

impl error::Error for DecodeError {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
None
}
}

impl fmt::Display for ValidationError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use crate::ValidationError::*;
use std::error::Error;

match *self {
MissingRequiredClaims(ref fields) => write!(
Expand All @@ -272,28 +231,20 @@ impl fmt::Display for ValidationError {
),
InvalidIssuer(ref iss) => write!(f, "Issuer of token is invalid: {:?}", iss),
InvalidAudience(ref aud) => write!(f, "Audience of token is invalid: {:?}", aud),

InvalidSignature
| WrongAlgorithmHeader
| KidMissing
| KeyNotFound
| UnsupportedKeyAlgorithm => write!(f, "{}", self.description()),
InvalidSignature => write!(f, "Invalid signature"),
WrongAlgorithmHeader => write!(
f,
"Token provided was signed or encrypted with an unexpected algorithm"
),
KidMissing => write!(f, "Header is missing kid"),
KeyNotFound => write!(f, "Key not found in JWKS"),
UnsupportedKeyAlgorithm => write!(f, "Algorithm of JWK not supported"),
}
}
}

impl fmt::Display for DecodeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use self::DecodeError::*;
use std::error::Error;

match *self {
InvalidToken => write!(f, "{}", self.description()),
PartsLengthError { expected, actual } => write!(
f,
"Expected {} parts in Compact JSON representation but got {}",
expected, actual
),
}
impl error::Error for ValidationError {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
None
}
}
62 changes: 31 additions & 31 deletions src/jwa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,12 +140,12 @@ pub enum KeyManagementAlgorithm {
/// ECDH-ES using Concat KDF and "A256KW" wrapping
#[serde(rename = "ECDH-ES+A256KW")]
ECDH_ES_A256KW,
/// Key wrapping with AES GCM using 128-bit key alg
/// Key wrapping with AES GCM using 128-bit key alg
A128GCMKW,
/// Key wrapping with AES GCM using 192-bit key alg.
/// This is [not supported](https://github.com/briansmith/ring/issues/112) by `ring`.
A192GCMKW,
/// Key wrapping with AES GCM using 256-bit key alg
/// Key wrapping with AES GCM using 256-bit key alg
A256GCMKW,
/// PBES2 with HMAC SHA-256 and "A128KW" wrapping
#[serde(rename = "PBES2-HS256+A128KW")]
Expand Down Expand Up @@ -179,13 +179,13 @@ pub enum KeyManagementAlgorithmType {
#[derive(Debug, Eq, PartialEq, Copy, Clone, Serialize, Deserialize)]
#[allow(non_camel_case_types)]
pub enum ContentEncryptionAlgorithm {
/// AES_128_CBC_HMAC_SHA_256 authenticated encryption algorithm enc
/// AES_128_CBC_HMAC_SHA_256 authenticated encryption algorithm enc
#[serde(rename = "A128CBC-HS256")]
A128CBC_HS256,
/// AES_192_CBC_HMAC_SHA_384 authenticated encryption algorithm enc
/// AES_192_CBC_HMAC_SHA_384 authenticated encryption algorithm enc
#[serde(rename = "A192CBC-HS384")]
A192CBC_HS384,
/// AES_256_CBC_HMAC_SHA_512 authenticated encryption algorithm enc
/// AES_256_CBC_HMAC_SHA_512 authenticated encryption algorithm enc
#[serde(rename = "A256CBC-HS512")]
A256CBC_HS512,
/// AES GCM using 128-bit key
Expand Down Expand Up @@ -491,10 +491,10 @@ impl KeyManagementAlgorithm {
) -> Result<jwk::JWK<Empty>, Error> {
let key = content_alg.generate_key()?;
Ok(jwk::JWK {
algorithm: jwk::AlgorithmParameters::OctetKey {
algorithm: jwk::AlgorithmParameters::OctetKey(jwk::OctetKeyParameters {
value: key,
key_type: Default::default(),
},
}),
common: jwk::CommonParameters {
public_key_use: Some(jwk::PublicKeyUse::Encryption),
algorithm: Some(Algorithm::ContentEncryption(content_alg)),
Expand Down Expand Up @@ -584,10 +584,10 @@ impl KeyManagementAlgorithm {

let cek = aes_gcm_decrypt(algorithm, encrypted, key)?;
Ok(jwk::JWK {
algorithm: jwk::AlgorithmParameters::OctetKey {
algorithm: jwk::AlgorithmParameters::OctetKey(jwk::OctetKeyParameters {
value: cek,
key_type: Default::default(),
},
}),
common: jwk::CommonParameters {
public_key_use: Some(jwk::PublicKeyUse::Encryption),
algorithm: Some(Algorithm::ContentEncryption(content_alg)),
Expand Down Expand Up @@ -1094,10 +1094,10 @@ mod tests {
let key = jwk::JWK::<Empty> {
common: Default::default(),
additional: Default::default(),
algorithm: jwk::AlgorithmParameters::OctetKey {
algorithm: jwk::AlgorithmParameters::OctetKey(jwk::OctetKeyParameters {
key_type: Default::default(),
value: key,
},
}),
};

let encrypted = not_err!(aes_gcm_encrypt(
Expand All @@ -1122,10 +1122,10 @@ mod tests {
let key = jwk::JWK::<Empty> {
common: Default::default(),
additional: Default::default(),
algorithm: jwk::AlgorithmParameters::OctetKey {
algorithm: jwk::AlgorithmParameters::OctetKey(jwk::OctetKeyParameters {
key_type: Default::default(),
value: key,
},
}),
};

let encrypted = not_err!(aes_gcm_encrypt(
Expand All @@ -1150,10 +1150,10 @@ mod tests {
let key = jwk::JWK::<Empty> {
common: Default::default(),
additional: Default::default(),
algorithm: jwk::AlgorithmParameters::OctetKey {
algorithm: jwk::AlgorithmParameters::OctetKey(jwk::OctetKeyParameters {
key_type: Default::default(),
value: key,
},
}),
};

let encrypted = not_err!(aes_gcm_encrypt(
Expand All @@ -1177,10 +1177,10 @@ mod tests {
let key = jwk::JWK::<Empty> {
common: Default::default(),
additional: Default::default(),
algorithm: jwk::AlgorithmParameters::OctetKey {
algorithm: jwk::AlgorithmParameters::OctetKey(jwk::OctetKeyParameters {
key_type: Default::default(),
value: key,
},
}),
};

let encrypted = not_err!(aes_gcm_encrypt(
Expand All @@ -1205,10 +1205,10 @@ mod tests {
let key = jwk::JWK::<Empty> {
common: Default::default(),
additional: Default::default(),
algorithm: jwk::AlgorithmParameters::OctetKey {
algorithm: jwk::AlgorithmParameters::OctetKey(jwk::OctetKeyParameters {
key_type: Default::default(),
value: key,
},
}),
};

let cek_alg = KeyManagementAlgorithm::DirectSymmetricKey;
Expand All @@ -1228,10 +1228,10 @@ mod tests {
let key = jwk::JWK::<Empty> {
common: Default::default(),
additional: Default::default(),
algorithm: jwk::AlgorithmParameters::OctetKey {
algorithm: jwk::AlgorithmParameters::OctetKey(jwk::OctetKeyParameters {
key_type: Default::default(),
value: key,
},
}),
};

let cek_alg = KeyManagementAlgorithm::A128GCMKW;
Expand All @@ -1257,10 +1257,10 @@ mod tests {
let key = jwk::JWK::<Empty> {
common: Default::default(),
additional: Default::default(),
algorithm: jwk::AlgorithmParameters::OctetKey {
algorithm: jwk::AlgorithmParameters::OctetKey(jwk::OctetKeyParameters {
key_type: Default::default(),
value: key,
},
}),
};

let cek_alg = KeyManagementAlgorithm::A256GCMKW;
Expand All @@ -1285,10 +1285,10 @@ mod tests {
let key = jwk::JWK::<Empty> {
common: Default::default(),
additional: Default::default(),
algorithm: jwk::AlgorithmParameters::OctetKey {
algorithm: jwk::AlgorithmParameters::OctetKey(jwk::OctetKeyParameters {
key_type: Default::default(),
value: key,
},
}),
};

let options = EncryptionOptions::AES_GCM {
Expand Down Expand Up @@ -1317,10 +1317,10 @@ mod tests {
let key = jwk::JWK::<Empty> {
common: Default::default(),
additional: Default::default(),
algorithm: jwk::AlgorithmParameters::OctetKey {
algorithm: jwk::AlgorithmParameters::OctetKey(jwk::OctetKeyParameters {
key_type: Default::default(),
value: key,
},
}),
};

let options = EncryptionOptions::AES_GCM {
Expand Down Expand Up @@ -1365,10 +1365,10 @@ mod tests {
let key = jwk::JWK::<Empty> {
common: Default::default(),
additional: Default::default(),
algorithm: jwk::AlgorithmParameters::OctetKey {
algorithm: jwk::AlgorithmParameters::OctetKey(jwk::OctetKeyParameters {
key_type: Default::default(),
value: key,
},
}),
};

let options = EncryptionOptions::AES_GCM {
Expand All @@ -1393,10 +1393,10 @@ mod tests {
let key = jwk::JWK::<Empty> {
common: Default::default(),
additional: Default::default(),
algorithm: jwk::AlgorithmParameters::OctetKey {
algorithm: jwk::AlgorithmParameters::OctetKey(jwk::OctetKeyParameters {
key_type: Default::default(),
value: key,
},
}),
};

let options = EncryptionOptions::AES_GCM {
Expand Down
Loading

0 comments on commit 6162415

Please sign in to comment.