Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: use case where RSA to and from JWK would cause an issue #37

Merged
merged 1 commit into from
Dec 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@

Loading