diff --git a/Sources/Crypto/RSA/RSA.swift b/Sources/Crypto/RSA/RSA.swift index ef6c1fe..53b8903 100644 --- a/Sources/Crypto/RSA/RSA.swift +++ b/Sources/Crypto/RSA/RSA.swift @@ -23,15 +23,12 @@ public final class RSA { // MARK: Static /// RSA using SHA256 digest. - @available(*, deprecated, message: "Use sign(_:algorithm:format:key:) or verify(_:algorithm:signs:format:key:)") public static var SHA256: RSA { return .init(algorithm: .sha256) } /// RSA using SHA384 digest. - @available(*, deprecated, message: "Use sign(_:algorithm:format:key:) or verify(_:algorithm:signs:format:key:)") public static var SHA384: RSA { return .init(algorithm: .sha384) } /// RSA using SHA512 digest. - @available(*, deprecated, message: "Use sign(_:algorithm:format:key:) or verify(_:algorithm:signs:format:key:)") public static var SHA512: RSA { return .init(algorithm: .sha512) } // MARK: Properties @@ -39,25 +36,22 @@ public final class RSA { /// The hashing algorithm to use, (e.g., SHA512). See `DigestAlgorithm`. public let algorithm: DigestAlgorithm - @available(*, deprecated, message: "Use sign(_:algorithm:format:key:) or verify(_:algorithm:signs:format:key:)") - public init(algorithm: DigestAlgorithm) { - self.algorithm = algorithm - } - // MARK: Init - /// Creates a new RSA cipher with the default unsafe md4 DigestAlgorithm. - /// You should use the sign and verify methods to provide a safer algorithm. - public init() { - self.algorithm = .md4 - } - - @available(*, deprecated, message: "Use sign(_:algorithm:format:key:)") - public func sign(_ input: LosslessDataConvertible, format: RSAInputFormat = .message, key: RSAKey) throws -> Data { - return try sign(input, algorithm: self.algorithm, format: format, key: key) + /// Creates a new RSA cipher using the supplied `DigestAlgorithm`. + /// + /// You can use the convenience static variables on `RSA` for common algorithms. + /// + /// let ciphertext = try RSA.SHA512.sign("vapor", key: .private(pem: ...)) + /// + /// You can also use this method to manually create an `RSA`. + /// + /// let rsa = RSA(algorithm: .sha512) + /// + public init(algorithm: DigestAlgorithm) { + self.algorithm = algorithm } - // MARK: Methods /// Signs the supplied input (in format specified by `format`). @@ -67,11 +61,10 @@ public final class RSA { /// - parameters: /// - input: Plaintext message or message digest to sign. /// - format: Format of the input, either plaintext message or digest. - /// - algorithm: Digest algorithm to use. /// - key: `RSAKey` to use for signing this data. /// - returns: RSA signature for this data. /// - throws: `CryptoError` if signing fails or data conversion fails. - public func sign(_ input: LosslessDataConvertible, algorithm: DigestAlgorithm, format: RSAInputFormat = .message, key: RSAKey) throws -> Data { + public func sign(_ input: LosslessDataConvertible, format: RSAInputFormat = .message, key: RSAKey) throws -> Data { switch key.type { case .public: throw CryptoError(identifier: "rsaSign", reason: "Cannot create RSA signature with a public key. A private key is required.") case .private: break @@ -110,11 +103,6 @@ public final class RSA { return sig } - @available(*, deprecated, message: "Use verify(_:algorithm:signs:format:key:)") - public func verify(_ signature: LosslessDataConvertible, signs input: LosslessDataConvertible, format: RSAInputFormat = .message, key: RSAKey) throws -> Bool { - return try verify(signature, algorithm: self.algorithm, signs: input, format: format, key: key) - } - /// Returns `true` if the supplied signature was created by signing the plaintext data. /// /// try RSA.SHA512.verify(ciphertext, signs: "vapor", key: .public(pem: ...)) @@ -126,7 +114,7 @@ public final class RSA { /// - key: `RSAKey` to use for signing this data. /// - returns: `true` if signature matches plaintext input. /// - throws: `CryptoError` if verification fails or data conversion fails. - public func verify(_ signature: LosslessDataConvertible, algorithm: DigestAlgorithm, signs input: LosslessDataConvertible, format: RSAInputFormat = .message, key: RSAKey) throws -> Bool { + public func verify(_ signature: LosslessDataConvertible, signs input: LosslessDataConvertible, format: RSAInputFormat = .message, key: RSAKey) throws -> Bool { var input = input.convertToData() let signature = signature.convertToData() @@ -161,7 +149,7 @@ public final class RSA { /// - key: `RSAKey` to use for decrypting this data. /// - returns: Decrypted data. /// - throws: `CryptoError` if encrypting fails. - public func decrypt(_ input: LosslessDataConvertible, padding: RSAPadding, key: RSAKey) throws -> Data { + public static func decrypt(_ input: LosslessDataConvertible, padding: RSAPadding, key: RSAKey) throws -> Data { return try rsaPkeyCrypt(input, padding: padding, key: key, coder: RSA_private_decrypt) } @@ -175,11 +163,11 @@ public final class RSA { /// - key: `RSAKey` to use for encrypting this data. /// - returns: Encrypted data. /// - throws: `CryptoError` if encrypting fails. - public func encrypt(_ input: LosslessDataConvertible, padding: RSAPadding, key: RSAKey) throws -> Data { + public static func encrypt(_ input: LosslessDataConvertible, padding: RSAPadding, key: RSAKey) throws -> Data { return try rsaPkeyCrypt(input, padding: padding, key: key, coder: RSA_public_encrypt) } - fileprivate func rsaPkeyCrypt(_ input: LosslessDataConvertible, padding: RSAPadding, key: RSAKey, coder: RSAPkeySymmetricCoder) throws -> Data { + fileprivate static func rsaPkeyCrypt(_ input: LosslessDataConvertible, padding: RSAPadding, key: RSAKey, coder: RSAPkeySymmetricCoder) throws -> Data { var outputData = Data(count: Int(RSA_size(key.c.pointer))) let outputLen = input.convertToData().withByteBuffer { inputBuffer in diff --git a/Tests/CryptoTests/RSATests.swift b/Tests/CryptoTests/RSATests.swift index 916a350..f600c19 100644 --- a/Tests/CryptoTests/RSATests.swift +++ b/Tests/CryptoTests/RSATests.swift @@ -6,26 +6,26 @@ class RSATests: XCTestCase { func testPrivateKey() throws { let plaintext = Data("vapor".utf8) let key: RSAKey = try .private(pem: privateKeyString) - let ciphertext = try RSA().sign(plaintext, algorithm: .sha512, key: key) - let verified = try RSA().verify(ciphertext, algorithm: .sha512, signs: plaintext, key: key) + let ciphertext = try RSA.SHA512.sign(plaintext, key: key) + let verified = try RSA.SHA512.verify(ciphertext, signs: plaintext, key: key) XCTAssertTrue(verified) } func testPublicKey() throws { let plaintext = Data("vapor".utf8) let key: RSAKey = try .public(pem: publicKeyString) - try XCTAssertTrue(RSA().verify(testSignature, algorithm: .sha512, signs: plaintext, key: key)) + try XCTAssertTrue(RSA.SHA512.verify(testSignature, signs: plaintext, key: key)) } func testFailure() throws { let plaintext = Data("vapor".utf8) let key: RSAKey = try .public(pem: publicKeyString) - try XCTAssertFalse(RSA().verify(Data("fake".utf8), algorithm: .sha512, signs: plaintext, key: key)) + try XCTAssertFalse(RSA.SHA512.verify(Data("fake".utf8), signs: plaintext, key: key)) } func testKey1024() throws { - let ciphertext = try RSA().sign("vapor", algorithm: .sha512, key: .private(pem: privateKey2String)) - let verified = try RSA().verify(ciphertext, algorithm: .sha512, signs: "vapor", key: .public(pem: publicKey2String)) + let ciphertext = try RSA.SHA512.sign("vapor", key: .private(pem: privateKey2String)) + let verified = try RSA.SHA512.verify(ciphertext, signs: "vapor", key: .public(pem: publicKey2String)) XCTAssertTrue(verified) } @@ -33,8 +33,8 @@ class RSATests: XCTestCase { let plaintext = Data("vapor".utf8) let rsaPublic: RSAKey = try .public(pem: publicKey3String) let rsaPrivate: RSAKey = try .private(pem: privateKey3String) - let ciphertext = try RSA().sign(plaintext, algorithm: .sha512, key: rsaPrivate) - let verified = try RSA().verify(ciphertext, algorithm: .sha512, signs: plaintext, key: rsaPublic) + let ciphertext = try RSA.SHA512.sign(plaintext, key: rsaPrivate) + let verified = try RSA.SHA512.verify(ciphertext, signs: plaintext, key: rsaPublic) XCTAssertTrue(verified) } @@ -42,8 +42,8 @@ class RSATests: XCTestCase { let plaintext = Data("vapor".utf8) let rsaPublic: RSAKey = try .public(pem: publicKey4String) let rsaPrivate: RSAKey = try .private(pem: privateKey4String) - let ciphertext = try RSA().sign(plaintext, algorithm: .sha512, key: rsaPrivate) - let verified = try RSA().verify(ciphertext, algorithm: .sha512, signs: plaintext, key: rsaPublic) + let ciphertext = try RSA.SHA512.sign(plaintext, key: rsaPrivate) + let verified = try RSA.SHA512.verify(ciphertext, signs: plaintext, key: rsaPublic) XCTAssertTrue(verified) } @@ -51,8 +51,8 @@ class RSATests: XCTestCase { let plaintext = Data("vapor".utf8) let rsaPublic: RSAKey = try .public(certificate: publicCertString) let rsaPrivate: RSAKey = try .private(pem: privateCertString) - let ciphertext = try RSA().sign(plaintext, algorithm: .sha512, key: rsaPrivate) - let verified = try RSA().verify(ciphertext, algorithm: .sha512, signs: plaintext, key: rsaPublic) + let ciphertext = try RSA.SHA512.sign(plaintext, key: rsaPrivate) + let verified = try RSA.SHA512.verify(ciphertext, signs: plaintext, key: rsaPublic) XCTAssertTrue(verified) } @@ -60,8 +60,8 @@ class RSATests: XCTestCase { let plaintext = Data("vapor".utf8) let rsaPublic: RSAKey = try .public(certificate: publicCertString) let rsaPrivate: RSAKey = try .private(pem: privateCertString) - let encryptedData = try RSA().encrypt(plaintext, padding: .pkcs1, key: rsaPublic) - let decryptedData = try RSA().decrypt(encryptedData, padding: .pkcs1, key: rsaPrivate) + let encryptedData = try RSA.encrypt(plaintext, padding: .pkcs1, key: rsaPublic) + let decryptedData = try RSA .decrypt(encryptedData, padding: .pkcs1, key: rsaPrivate) let decryptedPlaintext = String(data: decryptedData, encoding: .utf8) XCTAssertTrue(decryptedPlaintext == "vapor") }