diff --git a/README.md b/README.md index 9328b17..720661b 100644 --- a/README.md +++ b/README.md @@ -257,6 +257,14 @@ JWS is a standard for digitally signing arbitrary content, as detailed in [RFC 7 - PS512 (RSA PSS with SHA-512) - EdDSA (EdDSA using Ed25519) - [RFC 8037](https://datatracker.ietf.org/doc/html/rfc8037) +### Bouncy castle secp256k1 failsafe + +There is a difference between the signatures given by Bouncy castle a prominent cryptographic Java library and used with Nimbus JWT and bitcoin secp256k1. The signatures are in DER format and for some reason the R and S are reverted. + +To have signatures that are verifiable by Bouncy Castle you can set this flag `ES256KSigner.outputFormat = .der`, it will transform the signatures in DER format. + +With this in mind this library provides a functionality to enable verification of Nimbus/Bouncy Castle signatures, this can be enabled by setting the flag `ES256KVerifier.bouncyCastleFailSafe = true`. This process requires manipualtion of the internal signature, and reverses the R and S bytes, use it at your own risk since it can add security flaw. + Example: ```swift diff --git a/Sources/JSONWebAlgorithms/Signatures/Curve25519/EdDSASigner.swift b/Sources/JSONWebAlgorithms/Signatures/Curve25519/EdDSASigner.swift index 5133976..b9288ce 100644 --- a/Sources/JSONWebAlgorithms/Signatures/Curve25519/EdDSASigner.swift +++ b/Sources/JSONWebAlgorithms/Signatures/Curve25519/EdDSASigner.swift @@ -18,10 +18,10 @@ import CryptoKit import Foundation import JSONWebKey -struct EdDSASigner: Signer { - var algorithm: String { SigningAlgorithm.EdDSA.rawValue } +public struct EdDSASigner: Signer { + public var algorithm: String { SigningAlgorithm.EdDSA.rawValue } - func sign(data: Data, key: JWK) throws -> Data { + public func sign(data: Data, key: JWK) throws -> Data { guard let d = key.d else { throw CryptoError.notValidPrivateKey } let privateKey = try Curve25519.Signing.PrivateKey(rawRepresentation: d) return try privateKey.signature(for: data) diff --git a/Sources/JSONWebAlgorithms/Signatures/Curve25519/EdDSAVerifier.swift b/Sources/JSONWebAlgorithms/Signatures/Curve25519/EdDSAVerifier.swift index 7dc2801..e97dedf 100644 --- a/Sources/JSONWebAlgorithms/Signatures/Curve25519/EdDSAVerifier.swift +++ b/Sources/JSONWebAlgorithms/Signatures/Curve25519/EdDSAVerifier.swift @@ -18,10 +18,10 @@ import CryptoKit import Foundation import JSONWebKey -struct EdDSAVerifier: Verifier { - var algorithm: String { SigningAlgorithm.EdDSA.rawValue } +public struct EdDSAVerifier: Verifier { + public var algorithm: String { SigningAlgorithm.EdDSA.rawValue } - func verify(data: Data, signature: Data, key: JWK?) throws -> Bool { + public func verify(data: Data, signature: Data, key: JWK?) throws -> Bool { guard let x = key?.x else { throw CryptoError.notValidPublicKey } diff --git a/Sources/JSONWebAlgorithms/Signatures/EC/Signers/ES256KSigner.swift b/Sources/JSONWebAlgorithms/Signatures/EC/Signers/ES256KSigner.swift index b65e31a..249f052 100644 --- a/Sources/JSONWebAlgorithms/Signatures/EC/Signers/ES256KSigner.swift +++ b/Sources/JSONWebAlgorithms/Signatures/EC/Signers/ES256KSigner.swift @@ -18,13 +18,27 @@ import Foundation import JSONWebKey import secp256k1 -struct ES256KSigner: Signer { - var algorithm: String { SigningAlgorithm.ES256K.rawValue } +public struct ES256KSigner: Signer { + public enum SignatureFormat { + case raw + case der + } + + public static var outputFormat = ES256KSigner.SignatureFormat.raw + + public var algorithm: String { SigningAlgorithm.ES256K.rawValue } - func sign(data: Data, key: JWK) throws -> Data { + public func sign(data: Data, key: JWK) throws -> Data { guard let d = key.d else { throw CryptoError.notValidPrivateKey } let privateKey = try secp256k1.Signing.PrivateKey(dataRepresentation: d) let hash = SHA256.hash(data: data) - return try privateKey.signature(for: hash).dataRepresentation + let signature = try privateKey.signature(for: hash) + + switch Self.outputFormat { + case .raw: + return signature.dataRepresentation + case .der: + return try signature.derRepresentation + } } } diff --git a/Sources/JSONWebAlgorithms/Signatures/EC/Signers/ES256Signer.swift b/Sources/JSONWebAlgorithms/Signatures/EC/Signers/ES256Signer.swift index a0cd728..bee2999 100644 --- a/Sources/JSONWebAlgorithms/Signatures/EC/Signers/ES256Signer.swift +++ b/Sources/JSONWebAlgorithms/Signatures/EC/Signers/ES256Signer.swift @@ -18,10 +18,10 @@ import CryptoKit import Foundation import JSONWebKey -struct ES256Signer: Signer { - var algorithm: String { SigningAlgorithm.ES256.rawValue } +public struct ES256Signer: Signer { + public var algorithm: String { SigningAlgorithm.ES256.rawValue } - func sign(data: Data, key: JWK) throws -> Data { + public func sign(data: Data, key: JWK) throws -> Data { guard let d = key.d else { throw CryptoError.notValidPrivateKey } let privateKey = try P256.Signing.PrivateKey(rawRepresentation: d) let hash = SHA256.hash(data: data) diff --git a/Sources/JSONWebAlgorithms/Signatures/EC/Signers/ES384Signer.swift b/Sources/JSONWebAlgorithms/Signatures/EC/Signers/ES384Signer.swift index b86f66d..edf0ac5 100644 --- a/Sources/JSONWebAlgorithms/Signatures/EC/Signers/ES384Signer.swift +++ b/Sources/JSONWebAlgorithms/Signatures/EC/Signers/ES384Signer.swift @@ -18,10 +18,10 @@ import CryptoKit import Foundation import JSONWebKey -struct ES384Signer: Signer { - var algorithm: String { SigningAlgorithm.ES384.rawValue } +public struct ES384Signer: Signer { + public var algorithm: String { SigningAlgorithm.ES384.rawValue } - func sign(data: Data, key: JWK) throws -> Data { + public func sign(data: Data, key: JWK) throws -> Data { guard let d = key.d else { throw CryptoError.notValidPrivateKey } let privateKey = try P384.Signing.PrivateKey(rawRepresentation: d) let hash = SHA384.hash(data: data) diff --git a/Sources/JSONWebAlgorithms/Signatures/EC/Signers/ES521Signer.swift b/Sources/JSONWebAlgorithms/Signatures/EC/Signers/ES521Signer.swift index cf5f52e..e7263e3 100644 --- a/Sources/JSONWebAlgorithms/Signatures/EC/Signers/ES521Signer.swift +++ b/Sources/JSONWebAlgorithms/Signatures/EC/Signers/ES521Signer.swift @@ -18,10 +18,10 @@ import CryptoKit import Foundation import JSONWebKey -struct ES512Signer: Signer { - var algorithm: String { SigningAlgorithm.ES512.rawValue } +public struct ES512Signer: Signer { + public var algorithm: String { SigningAlgorithm.ES512.rawValue } - func sign(data: Data, key: JWK) throws -> Data { + public func sign(data: Data, key: JWK) throws -> Data { guard let d = key.d else { throw CryptoError.notValidPrivateKey } let privateKey = try P521.Signing.PrivateKey(rawRepresentation: d) let hash = SHA512.hash(data: data) diff --git a/Sources/JSONWebAlgorithms/Signatures/EC/Verifiers/ES256KVerifier.swift b/Sources/JSONWebAlgorithms/Signatures/EC/Verifiers/ES256KVerifier.swift index c4307ec..58ef4f0 100644 --- a/Sources/JSONWebAlgorithms/Signatures/EC/Verifiers/ES256KVerifier.swift +++ b/Sources/JSONWebAlgorithms/Signatures/EC/Verifiers/ES256KVerifier.swift @@ -18,17 +18,74 @@ import Foundation import JSONWebKey import secp256k1 -struct ES256KVerifier: Verifier { - var algorithm: String { SigningAlgorithm.ES256K.rawValue } +public struct ES256KVerifier: Verifier { + public static var bouncyCastleFailSafe = false - func verify(data: Data, signature: Data, key: JWK?) throws -> Bool { + public var algorithm: String { SigningAlgorithm.ES256K.rawValue } + + public func verify(data: Data, signature: Data, key: JWK?) throws -> Bool { guard let x = key?.x, let y = key?.y else { throw CryptoError.notValidPublicKey } let publicKey = try secp256k1.Signing.PublicKey(dataRepresentation: [0x04] + x + y, format: .uncompressed) let hash = SHA256.hash(data: data) - return try publicKey.isValidSignature(getSignature(signature), for: hash) + guard try publicKey.isValidSignature(getSignature(signature), for: hash) else { + guard ES256KVerifier.bouncyCastleFailSafe else { + return false + } + let bcSignature = transcodeSignatureToDERBitcoin(derEncodedSig: signature) + return try publicKey.isValidSignature(getSignature(bcSignature), for: hash) + } + return true + } + + // This function helps transcode the signature from bouncy castle to bitcoin + private func transcodeSignatureToDERBitcoin(derEncodedSig: Data) -> Data { + // Helper to extract integer components from DER format + func extractInteger(from data: Data, at offset: inout Int) -> Data { + guard data[offset] == 0x02 else { + fatalError("Expected integer") + } + offset += 1 // Move past the 0x02 + + let length = Int(data[offset]) + offset += 1 // Move past the length byte + + let integerData = data[offset..<(offset + length)] + offset += length // Move past the integer data + return Data(integerData.reversed()) // Reverse the bytes + } + + var offset = 0 + + // Verify initial DER sequence byte and length + guard derEncodedSig[offset] == 0x30 else { + fatalError("Invalid DER encoding") + } + offset += 1 + + let _ = Int(derEncodedSig[offset]) // Total length (not used) + offset += 1 + + // Extract and reverse R and S + let reversedR = extractInteger(from: derEncodedSig, at: &offset) + let reversedS = extractInteger(from: derEncodedSig, at: &offset) + + // Re-encode to DER format + var derEncoded = Data([0x30]) // Start of DER sequence + let totalLength = reversedR.count + reversedS.count + 4 // Total length of the content + derEncoded.append(contentsOf: [UInt8(totalLength)]) + + // Append R + derEncoded.append(contentsOf: [0x02, UInt8(reversedR.count)]) + derEncoded.append(reversedR) + + // Append S + derEncoded.append(contentsOf: [0x02, UInt8(reversedS.count)]) + derEncoded.append(reversedS) + + return derEncoded } } diff --git a/Sources/JSONWebAlgorithms/Signatures/EC/Verifiers/ES256Verifier.swift b/Sources/JSONWebAlgorithms/Signatures/EC/Verifiers/ES256Verifier.swift index 7bd1b50..b74d29a 100644 --- a/Sources/JSONWebAlgorithms/Signatures/EC/Verifiers/ES256Verifier.swift +++ b/Sources/JSONWebAlgorithms/Signatures/EC/Verifiers/ES256Verifier.swift @@ -18,10 +18,10 @@ import CryptoKit import Foundation import JSONWebKey -struct ES256Verifier: Verifier { - var algorithm: String { SigningAlgorithm.ES256.rawValue } +public struct ES256Verifier: Verifier { + public var algorithm: String { SigningAlgorithm.ES256.rawValue } - func verify(data: Data, signature: Data, key: JWK?) throws -> Bool { + public func verify(data: Data, signature: Data, key: JWK?) throws -> Bool { guard let x = key?.x, let y = key?.y diff --git a/Sources/JSONWebAlgorithms/Signatures/EC/Verifiers/ES384Verifier.swift b/Sources/JSONWebAlgorithms/Signatures/EC/Verifiers/ES384Verifier.swift index bbe901b..6785906 100644 --- a/Sources/JSONWebAlgorithms/Signatures/EC/Verifiers/ES384Verifier.swift +++ b/Sources/JSONWebAlgorithms/Signatures/EC/Verifiers/ES384Verifier.swift @@ -18,10 +18,10 @@ import CryptoKit import Foundation import JSONWebKey -struct ES384Verifier: Verifier { - var algorithm: String { SigningAlgorithm.ES384.rawValue } +public struct ES384Verifier: Verifier { + public var algorithm: String { SigningAlgorithm.ES384.rawValue } - func verify(data: Data, signature: Data, key: JWK?) throws -> Bool { + public func verify(data: Data, signature: Data, key: JWK?) throws -> Bool { guard let x = key?.x, let y = key?.y diff --git a/Sources/JSONWebAlgorithms/Signatures/EC/Verifiers/ES521Verifier.swift b/Sources/JSONWebAlgorithms/Signatures/EC/Verifiers/ES521Verifier.swift index 98ebb21..0c18244 100644 --- a/Sources/JSONWebAlgorithms/Signatures/EC/Verifiers/ES521Verifier.swift +++ b/Sources/JSONWebAlgorithms/Signatures/EC/Verifiers/ES521Verifier.swift @@ -18,10 +18,10 @@ import CryptoKit import Foundation import JSONWebKey -struct ES521Verifier: Verifier { - var algorithm: String { SigningAlgorithm.ES512.rawValue } +public struct ES521Verifier: Verifier { + public var algorithm: String { SigningAlgorithm.ES512.rawValue } - func verify(data: Data, signature: Data, key: JWK?) throws -> Bool { + public func verify(data: Data, signature: Data, key: JWK?) throws -> Bool { guard let x = key?.x, let y = key?.y diff --git a/Sources/JSONWebAlgorithms/Signatures/HMAC/Signers/HS256Signer.swift b/Sources/JSONWebAlgorithms/Signatures/HMAC/Signers/HS256Signer.swift index b8f0324..fe62aa9 100644 --- a/Sources/JSONWebAlgorithms/Signatures/HMAC/Signers/HS256Signer.swift +++ b/Sources/JSONWebAlgorithms/Signatures/HMAC/Signers/HS256Signer.swift @@ -18,10 +18,10 @@ import CryptoKit import Foundation import JSONWebKey -struct HS256Signer: Signer { - var algorithm: String { SigningAlgorithm.HS256.rawValue } +public struct HS256Signer: Signer { + public var algorithm: String { SigningAlgorithm.HS256.rawValue } - func sign(data: Data, key: JWK) throws -> Data { + public func sign(data: Data, key: JWK) throws -> Data { guard let k = key.key else { throw CryptoError.notValidPrivateKey } let symmetryKey = SymmetricKey(data: k) return Data(HMAC.authenticationCode(for: data, using: symmetryKey)) diff --git a/Sources/JSONWebAlgorithms/Signatures/HMAC/Signers/HS384Signer.swift b/Sources/JSONWebAlgorithms/Signatures/HMAC/Signers/HS384Signer.swift index 794cc92..5357904 100644 --- a/Sources/JSONWebAlgorithms/Signatures/HMAC/Signers/HS384Signer.swift +++ b/Sources/JSONWebAlgorithms/Signatures/HMAC/Signers/HS384Signer.swift @@ -18,10 +18,10 @@ import CryptoKit import Foundation import JSONWebKey -struct HS384Signer: Signer { - var algorithm: String { SigningAlgorithm.HS384.rawValue } +public struct HS384Signer: Signer { + public var algorithm: String { SigningAlgorithm.HS384.rawValue } - func sign(data: Data, key: JWK) throws -> Data { + public func sign(data: Data, key: JWK) throws -> Data { guard let k = key.key else { throw CryptoError.notValidPrivateKey } let symmetryKey = SymmetricKey(data: k) return Data(HMAC.authenticationCode(for: data, using: symmetryKey)) diff --git a/Sources/JSONWebAlgorithms/Signatures/HMAC/Signers/HS512Signer.swift b/Sources/JSONWebAlgorithms/Signatures/HMAC/Signers/HS512Signer.swift index 027f1a4..7487792 100644 --- a/Sources/JSONWebAlgorithms/Signatures/HMAC/Signers/HS512Signer.swift +++ b/Sources/JSONWebAlgorithms/Signatures/HMAC/Signers/HS512Signer.swift @@ -18,10 +18,10 @@ import CryptoKit import Foundation import JSONWebKey -struct HS512Signer: Signer { - var algorithm: String { SigningAlgorithm.HS512.rawValue } +public struct HS512Signer: Signer { + public var algorithm: String { SigningAlgorithm.HS512.rawValue } - func sign(data: Data, key: JWK) throws -> Data { + public func sign(data: Data, key: JWK) throws -> Data { guard let k = key.key else { throw CryptoError.notValidPrivateKey } let symmetryKey = SymmetricKey(data: k) return Data(HMAC.authenticationCode(for: data, using: symmetryKey)) diff --git a/Sources/JSONWebAlgorithms/Signatures/HMAC/Verifiers/HS256Verifier.swift b/Sources/JSONWebAlgorithms/Signatures/HMAC/Verifiers/HS256Verifier.swift index 389737e..1fba423 100644 --- a/Sources/JSONWebAlgorithms/Signatures/HMAC/Verifiers/HS256Verifier.swift +++ b/Sources/JSONWebAlgorithms/Signatures/HMAC/Verifiers/HS256Verifier.swift @@ -18,10 +18,10 @@ import CryptoKit import Foundation import JSONWebKey -struct HS256Verifier: Verifier { - var algorithm: String { SigningAlgorithm.HS256.rawValue } +public struct HS256Verifier: Verifier { + public var algorithm: String { SigningAlgorithm.HS256.rawValue } - func verify(data: Data, signature: Data, key: JWK?) throws -> Bool { + public func verify(data: Data, signature: Data, key: JWK?) throws -> Bool { guard let k = key?.key else { throw CryptoError.notValidPrivateKey } let symmetryKey = SymmetricKey(data: k) return HMAC.isValidAuthenticationCode(signature, authenticating: data, using: symmetryKey) diff --git a/Sources/JSONWebAlgorithms/Signatures/HMAC/Verifiers/HS384Verifier.swift b/Sources/JSONWebAlgorithms/Signatures/HMAC/Verifiers/HS384Verifier.swift index f912ccb..2da7e12 100644 --- a/Sources/JSONWebAlgorithms/Signatures/HMAC/Verifiers/HS384Verifier.swift +++ b/Sources/JSONWebAlgorithms/Signatures/HMAC/Verifiers/HS384Verifier.swift @@ -18,10 +18,10 @@ import CryptoKit import Foundation import JSONWebKey -struct HS384Verifier: Verifier { - var algorithm: String { SigningAlgorithm.HS384.rawValue } +public struct HS384Verifier: Verifier { + public var algorithm: String { SigningAlgorithm.HS384.rawValue } - func verify(data: Data, signature: Data, key: JWK?) throws -> Bool { + public func verify(data: Data, signature: Data, key: JWK?) throws -> Bool { guard let k = key?.key else { throw CryptoError.notValidPrivateKey } let symmetryKey = SymmetricKey(data: k) return HMAC.isValidAuthenticationCode(signature, authenticating: data, using: symmetryKey) diff --git a/Sources/JSONWebAlgorithms/Signatures/HMAC/Verifiers/HS512Verifier.swift b/Sources/JSONWebAlgorithms/Signatures/HMAC/Verifiers/HS512Verifier.swift index d71e32f..e0e17c9 100644 --- a/Sources/JSONWebAlgorithms/Signatures/HMAC/Verifiers/HS512Verifier.swift +++ b/Sources/JSONWebAlgorithms/Signatures/HMAC/Verifiers/HS512Verifier.swift @@ -18,10 +18,10 @@ import CryptoKit import Foundation import JSONWebKey -struct HS512Verifier: Verifier { - var algorithm: String { SigningAlgorithm.HS512.rawValue } +public struct HS512Verifier: Verifier { + public var algorithm: String { SigningAlgorithm.HS512.rawValue } - func verify(data: Data, signature: Data, key: JWK?) throws -> Bool { + public func verify(data: Data, signature: Data, key: JWK?) throws -> Bool { guard let k = key?.key else { throw CryptoError.notValidPrivateKey } let symmetryKey = SymmetricKey(data: k) return HMAC.isValidAuthenticationCode(signature, authenticating: data, using: symmetryKey) diff --git a/Sources/JSONWebAlgorithms/Signatures/RSA/Signers/PS256Signer.swift b/Sources/JSONWebAlgorithms/Signatures/RSA/Signers/PS256Signer.swift index 9cd775e..26bb84c 100644 --- a/Sources/JSONWebAlgorithms/Signatures/RSA/Signers/PS256Signer.swift +++ b/Sources/JSONWebAlgorithms/Signatures/RSA/Signers/PS256Signer.swift @@ -18,10 +18,10 @@ import CryptoSwift import Foundation import JSONWebKey -struct PS256Signer: Signer { - var algorithm: String { SigningAlgorithm.PS256.rawValue } +public struct PS256Signer: Signer { + public var algorithm: String { SigningAlgorithm.PS256.rawValue } - func sign(data: Data, key: JWK) throws -> Data { + public func sign(data: Data, key: JWK) throws -> Data { guard let n = key.n, let e = key.e diff --git a/Sources/JSONWebAlgorithms/Signatures/RSA/Signers/PS384Signer.swift b/Sources/JSONWebAlgorithms/Signatures/RSA/Signers/PS384Signer.swift index f94aa12..b1d30a3 100644 --- a/Sources/JSONWebAlgorithms/Signatures/RSA/Signers/PS384Signer.swift +++ b/Sources/JSONWebAlgorithms/Signatures/RSA/Signers/PS384Signer.swift @@ -18,10 +18,10 @@ import CryptoSwift import Foundation import JSONWebKey -struct PS384Signer: Signer { - var algorithm: String { SigningAlgorithm.PS384.rawValue } +public struct PS384Signer: Signer { + public var algorithm: String { SigningAlgorithm.PS384.rawValue } - func sign(data: Data, key: JWK) throws -> Data { + public func sign(data: Data, key: JWK) throws -> Data { guard let n = key.n, let e = key.e diff --git a/Sources/JSONWebAlgorithms/Signatures/RSA/Signers/PS512Signer.swift b/Sources/JSONWebAlgorithms/Signatures/RSA/Signers/PS512Signer.swift index 24738fc..37ed56d 100644 --- a/Sources/JSONWebAlgorithms/Signatures/RSA/Signers/PS512Signer.swift +++ b/Sources/JSONWebAlgorithms/Signatures/RSA/Signers/PS512Signer.swift @@ -18,10 +18,10 @@ import CryptoSwift import Foundation import JSONWebKey -struct PS512Signer: Signer { - var algorithm: String { SigningAlgorithm.PS512.rawValue } +public struct PS512Signer: Signer { + public var algorithm: String { SigningAlgorithm.PS512.rawValue } - func sign(data: Data, key: JWK) throws -> Data { + public func sign(data: Data, key: JWK) throws -> Data { guard let n = key.n, let e = key.e diff --git a/Sources/JSONWebAlgorithms/Signatures/RSA/Signers/RS256Signer.swift b/Sources/JSONWebAlgorithms/Signatures/RSA/Signers/RS256Signer.swift index d86e78b..5927916 100644 --- a/Sources/JSONWebAlgorithms/Signatures/RSA/Signers/RS256Signer.swift +++ b/Sources/JSONWebAlgorithms/Signatures/RSA/Signers/RS256Signer.swift @@ -18,10 +18,10 @@ import CryptoSwift import Foundation import JSONWebKey -struct RS256Signer: Signer { - var algorithm: String { SigningAlgorithm.RS256.rawValue } +public struct RS256Signer: Signer { + public var algorithm: String { SigningAlgorithm.RS256.rawValue } - func sign(data: Data, key: JWK) throws -> Data { + public func sign(data: Data, key: JWK) throws -> Data { guard let n = key.n, let e = key.e diff --git a/Sources/JSONWebAlgorithms/Signatures/RSA/Signers/RS384Signer.swift b/Sources/JSONWebAlgorithms/Signatures/RSA/Signers/RS384Signer.swift index 25df972..fd0523f 100644 --- a/Sources/JSONWebAlgorithms/Signatures/RSA/Signers/RS384Signer.swift +++ b/Sources/JSONWebAlgorithms/Signatures/RSA/Signers/RS384Signer.swift @@ -18,10 +18,10 @@ import CryptoSwift import Foundation import JSONWebKey -struct RS384Signer: Signer { - var algorithm: String { SigningAlgorithm.RS384.rawValue } +public struct RS384Signer: Signer { + public var algorithm: String { SigningAlgorithm.RS384.rawValue } - func sign(data: Data, key: JWK) throws -> Data { + public func sign(data: Data, key: JWK) throws -> Data { guard let n = key.n, let e = key.e diff --git a/Sources/JSONWebAlgorithms/Signatures/RSA/Signers/RS512Signer.swift b/Sources/JSONWebAlgorithms/Signatures/RSA/Signers/RS512Signer.swift index 6117974..e2e8394 100644 --- a/Sources/JSONWebAlgorithms/Signatures/RSA/Signers/RS512Signer.swift +++ b/Sources/JSONWebAlgorithms/Signatures/RSA/Signers/RS512Signer.swift @@ -18,10 +18,10 @@ import CryptoSwift import Foundation import JSONWebKey -struct RS512Signer: Signer { - var algorithm: String { SigningAlgorithm.RS512.rawValue } +public struct RS512Signer: Signer { + public var algorithm: String { SigningAlgorithm.RS512.rawValue } - func sign(data: Data, key: JWK) throws -> Data { + public func sign(data: Data, key: JWK) throws -> Data { guard let n = key.n, let e = key.e diff --git a/Sources/JSONWebAlgorithms/Signatures/RSA/Verifiers/PS256Verifier.swift b/Sources/JSONWebAlgorithms/Signatures/RSA/Verifiers/PS256Verifier.swift index 6ab37ad..88a1420 100644 --- a/Sources/JSONWebAlgorithms/Signatures/RSA/Verifiers/PS256Verifier.swift +++ b/Sources/JSONWebAlgorithms/Signatures/RSA/Verifiers/PS256Verifier.swift @@ -18,10 +18,10 @@ import CryptoSwift import Foundation import JSONWebKey -struct PS256Verifier: Verifier { - var algorithm: String { SigningAlgorithm.PS256.rawValue } +public struct PS256Verifier: Verifier { + public var algorithm: String { SigningAlgorithm.PS256.rawValue } - func verify(data: Data, signature: Data, key: JWK?) throws -> Bool { + public func verify(data: Data, signature: Data, key: JWK?) throws -> Bool { guard let n = key?.n, let e = key?.e diff --git a/Sources/JSONWebAlgorithms/Signatures/RSA/Verifiers/PS384Verifier.swift b/Sources/JSONWebAlgorithms/Signatures/RSA/Verifiers/PS384Verifier.swift index 1f77d22..2e88405 100644 --- a/Sources/JSONWebAlgorithms/Signatures/RSA/Verifiers/PS384Verifier.swift +++ b/Sources/JSONWebAlgorithms/Signatures/RSA/Verifiers/PS384Verifier.swift @@ -18,10 +18,10 @@ import CryptoSwift import Foundation import JSONWebKey -struct PS384Verifier: Verifier { - var algorithm: String { SigningAlgorithm.PS384.rawValue } +public struct PS384Verifier: Verifier { + public var algorithm: String { SigningAlgorithm.PS384.rawValue } - func verify(data: Data, signature: Data, key: JWK?) throws -> Bool { + public func verify(data: Data, signature: Data, key: JWK?) throws -> Bool { guard let n = key?.n, let e = key?.e diff --git a/Sources/JSONWebAlgorithms/Signatures/RSA/Verifiers/PS512Verifier.swift b/Sources/JSONWebAlgorithms/Signatures/RSA/Verifiers/PS512Verifier.swift index 9590af4..faea991 100644 --- a/Sources/JSONWebAlgorithms/Signatures/RSA/Verifiers/PS512Verifier.swift +++ b/Sources/JSONWebAlgorithms/Signatures/RSA/Verifiers/PS512Verifier.swift @@ -18,10 +18,10 @@ import CryptoSwift import Foundation import JSONWebKey -struct PS512Verifier: Verifier { - var algorithm: String { SigningAlgorithm.PS512.rawValue } +public struct PS512Verifier: Verifier { + public var algorithm: String { SigningAlgorithm.PS512.rawValue } - func verify(data: Data, signature: Data, key: JWK?) throws -> Bool { + public func verify(data: Data, signature: Data, key: JWK?) throws -> Bool { guard let n = key?.n, let e = key?.e diff --git a/Sources/JSONWebAlgorithms/Signatures/RSA/Verifiers/RS256Verifier.swift b/Sources/JSONWebAlgorithms/Signatures/RSA/Verifiers/RS256Verifier.swift index 8f873e9..9008915 100644 --- a/Sources/JSONWebAlgorithms/Signatures/RSA/Verifiers/RS256Verifier.swift +++ b/Sources/JSONWebAlgorithms/Signatures/RSA/Verifiers/RS256Verifier.swift @@ -18,10 +18,10 @@ import CryptoSwift import Foundation import JSONWebKey -struct RS256Verifier: Verifier { - var algorithm: String { SigningAlgorithm.RS256.rawValue } +public struct RS256Verifier: Verifier { + public var algorithm: String { SigningAlgorithm.RS256.rawValue } - func verify(data: Data, signature: Data, key: JWK?) throws -> Bool { + public func verify(data: Data, signature: Data, key: JWK?) throws -> Bool { guard let n = key?.n, let e = key?.e diff --git a/Sources/JSONWebAlgorithms/Signatures/RSA/Verifiers/RS384Verifier.swift b/Sources/JSONWebAlgorithms/Signatures/RSA/Verifiers/RS384Verifier.swift index fff703f..deca849 100644 --- a/Sources/JSONWebAlgorithms/Signatures/RSA/Verifiers/RS384Verifier.swift +++ b/Sources/JSONWebAlgorithms/Signatures/RSA/Verifiers/RS384Verifier.swift @@ -18,10 +18,10 @@ import CryptoSwift import Foundation import JSONWebKey -struct RS384Verifier: Verifier { - var algorithm: String { SigningAlgorithm.RS384.rawValue } +public struct RS384Verifier: Verifier { + public var algorithm: String { SigningAlgorithm.RS384.rawValue } - func verify(data: Data, signature: Data, key: JWK?) throws -> Bool { + public func verify(data: Data, signature: Data, key: JWK?) throws -> Bool { guard let n = key?.n, let e = key?.e diff --git a/Sources/JSONWebAlgorithms/Signatures/RSA/Verifiers/RS512Verifier.swift b/Sources/JSONWebAlgorithms/Signatures/RSA/Verifiers/RS512Verifier.swift index 4abcece..40287a2 100644 --- a/Sources/JSONWebAlgorithms/Signatures/RSA/Verifiers/RS512Verifier.swift +++ b/Sources/JSONWebAlgorithms/Signatures/RSA/Verifiers/RS512Verifier.swift @@ -18,10 +18,10 @@ import CryptoSwift import Foundation import JSONWebKey -struct RS512Verifier: Verifier { - var algorithm: String { SigningAlgorithm.RS512.rawValue } +public struct RS512Verifier: Verifier { + public var algorithm: String { SigningAlgorithm.RS512.rawValue } - func verify(data: Data, signature: Data, key: JWK?) throws -> Bool { + public func verify(data: Data, signature: Data, key: JWK?) throws -> Bool { guard let n = key?.n, let e = key?.e diff --git a/Tests/JWATests/ES256KTests.swift b/Tests/JWATests/ES256KTests.swift index e2aa005..d924c56 100644 --- a/Tests/JWATests/ES256KTests.swift +++ b/Tests/JWATests/ES256KTests.swift @@ -16,6 +16,8 @@ @testable import JSONWebAlgorithms import JSONWebKey +import Tools +import secp256k1 import XCTest final class Secp256k1Tests: XCTestCase { @@ -30,4 +32,74 @@ final class Secp256k1Tests: XCTestCase { key: key )) } + + func testSecp256k1BouncyCastleSignatureVerify() throws { + let payload = try "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NksifQ.eyJub25jZSI6IjQ3YmM5ZmMwLWVhODAtNDlmOC04OTcxLWJjYzY0MmJmZDNjMCIsImlzcyI6ImRpZDpwcmlzbTphZjJlNGJiOWU1MTRmODg5ZTdkNTY2MDZjNmYzZWVhYmNmMDgxZTc0ZTQ4NDMwN2Q3NTQ4Mzg0Y2ZiOTE4ZTdlOkNzY0JDc1FCRW1RS0QyRjFkR2hsYm5ScFkyRjBhVzl1TUJBRVFrOEtDWE5sWTNBeU5UWnJNUklnTHM1aFNjUG50REY2WGY2RElhNVFoNkp5OUZpR1FVdzdEMi16UHZSWXdmTWFJTGZGX0k0bDktZkNiX1NtS3pEaDZaQnhPbzZXX0FrN3htbTRDQ1ZENUZfLUVsd0tCMjFoYzNSbGNqQVFBVUpQQ2dselpXTndNalUyYXpFU0lDN09ZVW5ENTdReGVsMy1neUd1VUllaWN2Ulloa0ZNT3c5dnN6NzBXTUh6R2lDM3hmeU9KZmZud21fMHBpc3c0ZW1RY1RxT2x2d0pPOFpwdUFnbFEtUmZfZyIsInZwIjp7IkBjb250ZXh0IjpbImh0dHBzOlwvXC93d3cudzMub3JnXC8yMDE4XC9wcmVzZW50YXRpb25zXC92MSJdLCJ0eXBlIjpbIlZlcmlmaWFibGVQcmVzZW50YXRpb24iXX0sImF1ZCI6ImRvbWFpbiJ9".tryToData() + + let publicKeyBase64 = "BC7OYUnD57Qxel3-gyGuUIeicvRYhkFMOw9vsz70WMHzt8X8jiX358Jv9KYrMOHpkHE6jpb8CTvGabgIJUPkX_4" + let publicKeyRaw = try Base64URL.decode(publicKeyBase64) + let publicKey = try secp256k1.Signing.PublicKey(dataRepresentation: publicKeyRaw, format: .uncompressed) + let sigantureBase64 = "MEQCIGRozcub8jmgwj32UaqY26JXD2Vw91pjP1boIyIFYWNgAiANARaJ_PnNCnTFFYUgajzml8kIhyIPQsVOchQDQz1RMA==" + let signatureRaw = try Base64URL.decode(sigantureBase64) + let swiftSigantureBase64 = "MEQCIGBjYQUiI-hWP2Na93BlD1ei25iqUfY9wqA58pvLzWhkAiAwUT1DAxRyTsVCDyKHCMmX5jxqIIUVxXQKzfn8iRYBDQ" + let swiftSignatureRaw = try Base64URL.decode(swiftSigantureBase64) + + print(swiftSignatureRaw.toHexString()) + print(signatureRaw.toHexString()) + + // Activate bouncy castle signature fail safe + ES256KVerifier.bouncyCastleFailSafe = true + + XCTAssertTrue(try ES256KVerifier().verify( + data: payload, + signature: swiftSignatureRaw, + key: publicKey.jwkRepresentation + )) + + XCTAssertTrue(try ES256KVerifier().verify( + data: payload, + signature: signatureRaw, + key: publicKey.jwkRepresentation + )) + } + + func testSecp256k1BouncyCastleSignatureVerifyFailIfFeatureNotActive() throws { + let payload = try "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NksifQ.eyJub25jZSI6IjQ3YmM5ZmMwLWVhODAtNDlmOC04OTcxLWJjYzY0MmJmZDNjMCIsImlzcyI6ImRpZDpwcmlzbTphZjJlNGJiOWU1MTRmODg5ZTdkNTY2MDZjNmYzZWVhYmNmMDgxZTc0ZTQ4NDMwN2Q3NTQ4Mzg0Y2ZiOTE4ZTdlOkNzY0JDc1FCRW1RS0QyRjFkR2hsYm5ScFkyRjBhVzl1TUJBRVFrOEtDWE5sWTNBeU5UWnJNUklnTHM1aFNjUG50REY2WGY2RElhNVFoNkp5OUZpR1FVdzdEMi16UHZSWXdmTWFJTGZGX0k0bDktZkNiX1NtS3pEaDZaQnhPbzZXX0FrN3htbTRDQ1ZENUZfLUVsd0tCMjFoYzNSbGNqQVFBVUpQQ2dselpXTndNalUyYXpFU0lDN09ZVW5ENTdReGVsMy1neUd1VUllaWN2Ulloa0ZNT3c5dnN6NzBXTUh6R2lDM3hmeU9KZmZud21fMHBpc3c0ZW1RY1RxT2x2d0pPOFpwdUFnbFEtUmZfZyIsInZwIjp7IkBjb250ZXh0IjpbImh0dHBzOlwvXC93d3cudzMub3JnXC8yMDE4XC9wcmVzZW50YXRpb25zXC92MSJdLCJ0eXBlIjpbIlZlcmlmaWFibGVQcmVzZW50YXRpb24iXX0sImF1ZCI6ImRvbWFpbiJ9".tryToData() + + let publicKeyBase64 = "BC7OYUnD57Qxel3-gyGuUIeicvRYhkFMOw9vsz70WMHzt8X8jiX358Jv9KYrMOHpkHE6jpb8CTvGabgIJUPkX_4" + let publicKeyRaw = try Base64URL.decode(publicKeyBase64) + let publicKey = try secp256k1.Signing.PublicKey(dataRepresentation: publicKeyRaw, format: .uncompressed) + let sigantureBase64 = "MEQCIGRozcub8jmgwj32UaqY26JXD2Vw91pjP1boIyIFYWNgAiANARaJ_PnNCnTFFYUgajzml8kIhyIPQsVOchQDQz1RMA==" + let signatureRaw = try Base64URL.decode(sigantureBase64) + let swiftSigantureBase64 = "MEQCIGBjYQUiI-hWP2Na93BlD1ei25iqUfY9wqA58pvLzWhkAiAwUT1DAxRyTsVCDyKHCMmX5jxqIIUVxXQKzfn8iRYBDQ" + let swiftSignatureRaw = try Base64URL.decode(swiftSigantureBase64) + + ES256KVerifier.bouncyCastleFailSafe = false + + XCTAssertTrue(try ES256KVerifier().verify( + data: payload, + signature: swiftSignatureRaw, + key: publicKey.jwkRepresentation + )) + + XCTAssertFalse(try ES256KVerifier().verify( + data: payload, + signature: signatureRaw, + key: publicKey.jwkRepresentation + )) + } + + func testSecp256k1CycleDerSignature() throws { + let payload = "Test".data(using: .utf8)! + let key = try secp256k1.Signing.PrivateKey(format: .uncompressed) + ES256KSigner.outputFormat = .der + + let signature = try ES256KSigner().sign(data: payload, key: key.jwkRepresentation) + + XCTAssertTrue(try ES256KVerifier().verify( + data: payload, + signature: signature, + key: key.jwkRepresentation + )) + } }