Skip to content

Commit

Permalink
fix: use case where RSA to and from JWK would cause an issue
Browse files Browse the repository at this point in the history
PR submitted for the fix krzyzanowskim/CryptoSwift#1060
  • Loading branch information
beatt83 committed Dec 7, 2024
1 parent 57fe5a0 commit 4228067
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 55 deletions.
7 changes: 6 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ let package = Package(
// For `secp256k1` support
.package(url: "https://github.com/GigaBitcoin/secp256k1.swift.git", .upToNextMinor(from: "0.15.0")),
// For `AES_CBC_HMAC_SHA2`, `PBES2` and RSA DER encoding support
.package(url: "https://github.com/krzyzanowskim/CryptoSwift.git", .upToNextMinor(from: "1.8.1"))
// Changing to a fork I made while I create a PR, since I found a bug
.package(url: "https://github.com/beatt83/CryptoSwift.git", .upToNextMinor(from: "1.8.5"))
// FOR `A256_CBC_HS512` with `ECDH-1PU-A256KW`
],
targets: [
Expand Down Expand Up @@ -98,6 +99,10 @@ let package = Package(
name: "JWTTests",
dependencies: ["JSONWebToken", "Tools"]
),
.testTarget(
name: "ExampleTests",
dependencies: ["JSONWebToken", "JSONWebKey", "JSONWebEncryption", "JSONWebSignature", "Tools"]
),
.target(
name: "Tools"
),
Expand Down
11 changes: 11 additions & 0 deletions Sources/JSONWebAlgorithms/KeyManagement/JWKRepresentable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,15 @@ extension Curve25519.Signing.PrivateKey: JWKRepresentable {
}
}

extension SymmetricKey: JWKRepresentable {
public var jwkRepresentation: JWK {
JWK(
keyType: .octetSequence,
key: Data(bytes)
)
}
}

extension Curve25519.Signing.PublicKey: JWKRepresentable {
/// Returns the JWK representation of a `Curve25519.KeyAgreement.PublicKey` instance.
public var jwkRepresentation: JWK {
Expand All @@ -359,6 +368,8 @@ extension CryptoSwift.RSA: JWKRepresentable {
JWK(
keyType: .rsa,
e: e.serialize(),
p: primes?.p.serialize(),
q: primes?.q.serialize(),
n: n.serialize(),
d: d?.serialize()
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,23 @@ public struct RSA15KeyUnwrap: KeyUnwrapping {
guard let e = using.e else {
throw JWK.Error.missingEComponent
}
guard let d = using.d else {
throw JWK.Error.missingDComponent
}
guard let p = using.p, let q = using.q else {
throw JWK.Error.missingPrimesComponent
}

let rsaPrivateKey = try CryptoSwift.RSA(
n: BigUInteger(n),
e: BigUInteger(e),
d: BigUInteger(d),
p: BigUInteger(p),
q: BigUInteger(q)
)
let rsaPrivateKey: CryptoSwift.RSA
if let p = using.p, let q = using.q, let d = using.d {
rsaPrivateKey = try CryptoSwift.RSA(
n: BigUInteger(n),
e: BigUInteger(e),
d: BigUInteger(d),
p: BigUInteger(p),
q: BigUInteger(q)
)
} else {
rsaPrivateKey = CryptoSwift.RSA(
n: BigUInteger(n),
e: BigUInteger(e),
d: using.d.map { BigUInteger($0) }
)
}
let derEncodedRSAPrivateKey = try rsaPrivateKey.externalRepresentation()
let attributes: [String: Any] = [
kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,23 @@ public struct RSAOAEP256KeyUnwrap: KeyUnwrapping {
guard let e = using.e else {
throw JWK.Error.missingEComponent
}
guard let d = using.d else {
throw JWK.Error.missingDComponent
}
guard let p = using.p, let q = using.q else {
throw JWK.Error.missingPrimesComponent

let rsaPrivateKey: CryptoSwift.RSA
if let p = using.p, let q = using.q, let d = using.d {
rsaPrivateKey = try CryptoSwift.RSA(
n: BigUInteger(n),
e: BigUInteger(e),
d: BigUInteger(d),
p: BigUInteger(p),
q: BigUInteger(q)
)
} else {
rsaPrivateKey = CryptoSwift.RSA(
n: BigUInteger(n),
e: BigUInteger(e),
d: using.d.map { BigUInteger($0) }
)
}

let rsaPrivateKey = try CryptoSwift.RSA(
n: BigUInteger(n),
e: BigUInteger(e),
d: BigUInteger(d),
p: BigUInteger(p),
q: BigUInteger(q)
)
let derEncodedRSAPrivateKey = try rsaPrivateKey.externalRepresentation()
let attributes: [String: Any] = [
kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,35 +40,24 @@ public struct RSAOAEPKeyUnwrap: KeyUnwrapping {
guard let e = using.e else {
throw JWK.Error.missingEComponent
}
guard let d = using.d else {
throw JWK.Error.missingDComponent
}
guard let p = using.p, let q = using.q else {
throw JWK.Error.missingPrimesComponent
let rsaPrivateKey: CryptoSwift.RSA
if let p = using.p, let q = using.q, let d = using.d {
rsaPrivateKey = try CryptoSwift.RSA(
n: BigUInteger(n),
e: BigUInteger(e),
d: BigUInteger(d),
p: BigUInteger(p),
q: BigUInteger(q)
)
} else {
rsaPrivateKey = CryptoSwift.RSA(
n: BigUInteger(n),
e: BigUInteger(e),
d: using.d.map { BigUInteger($0) }
)
}

let rsaPrivateKey = try CryptoSwift.RSA(
n: BigUInteger(n),
e: BigUInteger(e),
d: BigUInteger(d),
p: BigUInteger(p),
q: BigUInteger(q)
)
let derEncodedRSAPrivateKey = try rsaPrivateKey.externalRepresentation()
let attributes: [String: Any] = [
kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
kSecAttrKeyClass as String: kSecAttrKeyClassPrivate,
kSecAttrKeySizeInBits as String: n.count * 8,
kSecAttrIsPermanent as String: false,
]
var error: Unmanaged<CFError>?
guard let rsaSecKey = SecKeyCreateWithData(
derEncodedRSAPrivateKey as CFData,
attributes as CFDictionary,
&error
) else {
throw CryptoError.securityLayerError(internalStatus: nil, internalError: error?.takeRetainedValue())
}
let rsaSecKey = try rsaPrivateKey.getSecKey()
let secKeyAlgorithm = SecKeyAlgorithm.rsaEncryptionOAEPSHA1
var decryptionError: Unmanaged<CFError>?
guard let plaintext = SecKeyCreateDecryptedData(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@ import Security

extension RSA {
func getSecKey() throws -> SecKey {
// CryptoSwift doesnt make much sense here, if you call externalRepresentation the condiction for public or private is if the primes exist
let raw = try externalRepresentation()
let attributes: [String: Any] = [
kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
kSecAttrKeyClass as String: d != nil ? kSecAttrKeyClassPrivate : kSecAttrKeyClassPublic,
kSecAttrKeyClass as String: d == nil ? kSecAttrKeyClassPublic : kSecAttrKeyClassPrivate,
kSecAttrKeySizeInBits as String: keySize,
kSecAttrIsPermanent as String: false
]
Expand Down
1 change: 1 addition & 0 deletions Tests/ExampleTests/ExampleTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

0 comments on commit 4228067

Please sign in to comment.