Skip to content
This repository has been archived by the owner on Sep 3, 2020. It is now read-only.

Commit

Permalink
code review
Browse files Browse the repository at this point in the history
  • Loading branch information
FranzBusch committed May 29, 2018
1 parent 966fc22 commit 177baf2
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 43 deletions.
46 changes: 17 additions & 29 deletions Sources/Crypto/RSA/RSA.swift
Expand Up @@ -23,41 +23,35 @@ 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

/// 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`).
Expand All @@ -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
Expand Down Expand Up @@ -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: ...))
Expand All @@ -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()

Expand Down Expand Up @@ -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)
}

Expand All @@ -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
Expand Down
28 changes: 14 additions & 14 deletions Tests/CryptoTests/RSATests.swift
Expand Up @@ -6,62 +6,62 @@ 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)
}

func testKey2048() throws {
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)
}

func testKey4096() throws {
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)
}

func testKeyCert() throws {
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)
}

func testEncrypt() throws {
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")
}
Expand Down

0 comments on commit 177baf2

Please sign in to comment.