Skip to content

Commit

Permalink
fix: Certificate.PublicKey RSA parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
amosavian committed Nov 6, 2023
1 parent 468d085 commit 8fcb9e9
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 20 deletions.
76 changes: 57 additions & 19 deletions Sources/JWSETKit/Cryptography/Certificate/X509Certificate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,36 +17,74 @@ import Crypto
import _CryptoExtras
#endif

extension Certificate.PublicKey {
extension Certificate.PublicKey: JSONWebValidatingKey {
public var storage: JSONWebValueStorage {
(try? jsonWebKey().storage) ?? .init()
}

public static func create(storage: JSONWebValueStorage) throws -> X509.Certificate.PublicKey {
if let key = try? P256.Signing.PublicKey.create(storage: storage) {
return .init(key)
} else if let key = try? P384.Signing.PublicKey.create(storage: storage) {
return .init(key)
} else if let key = try? P521.Signing.PublicKey.create(storage: storage) {
return .init(key)
}
#if canImport(CommonCrypto)
if let key = try? SecKey.create(storage: storage).publicKey {
let der = try handle { error in
SecKeyCopyExternalRepresentation(key, &error)
}
return try .init(derEncoded: der as Data)
}
#elseif canImport(_CryptoExtras)
if let key = try? _RSA.Signing.PublicKey.create(storage: storage) {
return .init(key)
}
#else
// This should never happen as CommonCrypto is available on Darwin platforms
// and CryptoSwift is used on non-Darwin platform.
fatalError("Unimplemented")
#endif
throw JSONWebKeyError.unknownKeyType
}

public func verifySignature<S, D>(_ signature: S, for data: D, using algorithm: JSONWebSignatureAlgorithm) throws where S: DataProtocol, D: DataProtocol {
try jsonWebKey().verifySignature(signature, for: data, using: algorithm)
}

/// Generates a key object from the public key inside certificate.
///
/// - Returns: A public key to validate signatures.
public func jsonWebKey() throws -> any JSONWebValidatingKey {
#if canImport(CommonCrypto)
private func jsonWebKey() throws -> any JSONWebValidatingKey {
if let key = P256.Signing.PublicKey(self) {
return key
} else if let key = P384.Signing.PublicKey(self) {
return key
} else if let key = P521.Signing.PublicKey(self) {
return key
} else if let key = try SecCertificateCreateWithData(kCFAllocatorDefault, derRepresentation as CFData)?.publicKey {
return key
} else {
throw JSONWebKeyError.unknownKeyType
}
#else
if let key = P256.Signing.PublicKey(self) {
return key
} else if let key = P384.Signing.PublicKey(self) {
return key
} else if let key = P521.Signing.PublicKey(self) {
return key
} else if let key = _RSA.Signing.PublicKey(self) {
#if canImport(CommonCrypto)
let rsaKey = try? handle { error in
let attributes = [
kSecAttrKeyType: kSecAttrKeyTypeRSA,
kSecAttrKeyClass: kSecAttrKeyClassPublic,
] as CFDictionary
return try? SecKeyCreateWithData(derRepresentation as CFData, attributes, &error)
}
if let rsaKey {
return rsaKey
}
#elseif canImport(_CryptoExtras)
if let key = _RSA.Signing.PublicKey(self) {
return key
} else {
throw JSONWebKeyError.unknownKeyType
}
#else
// This should never happen as CommonCrypto is available on Darwin platforms
// and CryptoSwift is used on non-Darwin platform.
fatalError("Unimplemented")
#endif
throw JSONWebKeyError.unknownKeyType
}
}

Expand All @@ -70,7 +108,7 @@ extension DERImplicitlyTaggable {

extension Certificate: JSONWebValidatingKey {
public var storage: JSONWebValueStorage {
var key = AnyJSONWebKey(storage: (try? publicKey.jsonWebKey().storage) ?? .init())
var key = AnyJSONWebKey(storage: publicKey.storage)
key.certificateChain = [self]
return key.storage
}
Expand All @@ -84,7 +122,7 @@ extension Certificate: JSONWebValidatingKey {
}

public func verifySignature<S, D>(_ signature: S, for data: D, using algorithm: JSONWebSignatureAlgorithm) throws where S: DataProtocol, D: DataProtocol {
try publicKey.jsonWebKey().verifySignature(signature, for: data, using: algorithm)
try publicKey.verifySignature(signature, for: data, using: algorithm)
}
}

Expand Down
2 changes: 1 addition & 1 deletion Sources/JWSETKit/Cryptography/Symmetric/AES-CBC-HMAC.swift
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ public struct JSONWebKeyAESCBCHMAC: MutableJSONWebKey, JSONWebSealingKey, JSONWe
}

private func hmac(_ data: Data) throws -> Data {
switch tagLength * 2 {
switch try symmetricKey.bitCount / 8 {
case SHA256.byteCount:
var hmac = try HMAC<SHA256>(key: hmacSymmetricKey)
hmac.update(data: data)
Expand Down

0 comments on commit 8fcb9e9

Please sign in to comment.