From 85b04839f104c659b59e95c0dd1bad6ba94a9808 Mon Sep 17 00:00:00 2001 From: andy Date: Mon, 25 Feb 2019 13:27:07 +0000 Subject: [PATCH 01/11] rebased to master --- Sources/CryptorRSA/CryptorRSA.swift | 30 +++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/Sources/CryptorRSA/CryptorRSA.swift b/Sources/CryptorRSA/CryptorRSA.swift index ec52945..a8d2bfe 100644 --- a/Sources/CryptorRSA/CryptorRSA.swift +++ b/Sources/CryptorRSA/CryptorRSA.swift @@ -453,8 +453,20 @@ public class CryptorRSA { // Assign size of the corresponding cipher's IV let IVLength = EVP_CIPHER_iv_length(.make(optional: enc)) let iv = UnsafeMutablePointer.allocate(capacity: Int(IVLength)) - let encrypted = UnsafeMutablePointer.allocate(capacity: self.data.count + Int(IVLength)) + defer { + #if swift(>=4.1) + ek?.deallocate() + ekPtr.deallocate() + iv.deallocate() + encrypted.deallocate() + #else + ek?.deallocate(capacity: Int(EVP_PKEY_size(evp_key))) + ekPtr.deallocate(capacity: MemoryLayout.size) + iv.deallocate(capacity: Int(IVLength)) + encrypted.deallocate(capacity: self.data.count + Int(IVLength)) + #endif + } var encKeyLength: Int32 = 0 var processedLength: Int32 = 0 var encLength: Int32 = 0 @@ -651,7 +663,13 @@ public class CryptorRSA { var decMsgLen: Int32 = 0 let decrypted = UnsafeMutablePointer.allocate(capacity: Int(encryptedData.count + encryptedIV.count)) - + defer { + #if swift(>=4.1) + decrypted.deallocate() + #else + decrypted.deallocate(capacity: Int(encryptedData.count + encryptedIV.count)) + #endif + } // EVP_OpenInit returns 0 on error or the recovered secret key size if successful status = encryptedKey.withUnsafeBytes({ (ek: UnsafePointer) -> Int32 in return encryptedIV.withUnsafeBytes({ (iv: UnsafePointer) -> Int32 in @@ -756,6 +774,14 @@ public class CryptorRSA { EVP_DigestSignFinal(md_ctx, nil, &sig_len) let sig = UnsafeMutablePointer.allocate(capacity: sig_len) + defer { + #if swift(>=4.1) + sig.deallocate() + #else + sig.deallocate(capacity: sig_len) + #endif + } + rc = EVP_DigestSignFinal(md_ctx, sig, &sig_len) guard rc == 1, sig_len > 0 else { let source = "Signing failed." From 750c033142aeec996927e7cd240027dc7a6e26e9 Mon Sep 17 00:00:00 2001 From: andy Date: Mon, 25 Feb 2019 14:33:24 +0000 Subject: [PATCH 02/11] Add key frees --- Sources/CryptorRSA/CryptorRSA.swift | 14 ++++++++++++-- Sources/CryptorRSA/CryptorRSAKey.swift | 3 +++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Sources/CryptorRSA/CryptorRSA.swift b/Sources/CryptorRSA/CryptorRSA.swift index a8d2bfe..f04ce43 100644 --- a/Sources/CryptorRSA/CryptorRSA.swift +++ b/Sources/CryptorRSA/CryptorRSA.swift @@ -743,6 +743,9 @@ public class CryptorRSA { // convert RSA key to EVP let evp_key = EVP_PKEY_new() + defer { + EVP_PKEY_free(evp_key) + } var rc = EVP_PKEY_set1_RSA(evp_key, .make(optional: key.reference)) guard rc == 1 else { let source = "Couldn't create key reference from key data" @@ -758,7 +761,9 @@ public class CryptorRSA { // Provide a pkey_ctx to EVP_DigestSignInit so that the EVP_PKEY_CTX of the signing operation // is written to it, to allow alternative signing options to be set var pkey_ctx = EVP_PKEY_CTX_new(evp_key, nil) - + defer { + EVP_PKEY_CTX_free(pkey_ctx) + } EVP_DigestSignInit(md_ctx, &pkey_ctx, .make(optional: md), nil, evp_key) // Now that Init has initialized pkey_ctx, set the padding option @@ -852,6 +857,9 @@ public class CryptorRSA { // convert RSA key to EVP let evp_key = EVP_PKEY_new() + defer { + EVP_PKEY_free(evp_key) + } var rc = EVP_PKEY_set1_RSA(evp_key, .make(optional: key.reference)) guard rc == 1 else { let source = "Couldn't create key reference from key data" @@ -867,7 +875,9 @@ public class CryptorRSA { // Provide a pkey_ctx to EVP_DigestSignInit so that the EVP_PKEY_CTX of the signing operation // is written to it, to allow alternative signing options to be set var pkey_ctx = EVP_PKEY_CTX_new(evp_key, nil) - + defer { + EVP_PKEY_CTX_free(pkey_ctx) + } EVP_DigestVerifyInit(md_ctx, &pkey_ctx, .make(optional: md), nil, evp_key) // Now that EVP_DigestVerifyInit has initialized pkey_ctx, set the padding option diff --git a/Sources/CryptorRSA/CryptorRSAKey.swift b/Sources/CryptorRSA/CryptorRSAKey.swift index 12e5832..183d0ce 100644 --- a/Sources/CryptorRSA/CryptorRSAKey.swift +++ b/Sources/CryptorRSA/CryptorRSAKey.swift @@ -610,6 +610,9 @@ extension CryptorRSA { #if os(Linux) var publicKeyBytes: Data? + deinit { + RSA_free(reference) + } #endif /// Represents the type of key data contained. From 547d1782c658fca362872c98ff5de8823d375ceb Mon Sep 17 00:00:00 2001 From: andy Date: Mon, 25 Feb 2019 15:12:36 +0000 Subject: [PATCH 03/11] Added RSAKey free --- Sources/CryptorRSA/CryptorRSA.swift | 6 ------ Sources/CryptorRSA/CryptorRSAKey.swift | 6 +++--- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/Sources/CryptorRSA/CryptorRSA.swift b/Sources/CryptorRSA/CryptorRSA.swift index f04ce43..78e99c7 100644 --- a/Sources/CryptorRSA/CryptorRSA.swift +++ b/Sources/CryptorRSA/CryptorRSA.swift @@ -761,9 +761,6 @@ public class CryptorRSA { // Provide a pkey_ctx to EVP_DigestSignInit so that the EVP_PKEY_CTX of the signing operation // is written to it, to allow alternative signing options to be set var pkey_ctx = EVP_PKEY_CTX_new(evp_key, nil) - defer { - EVP_PKEY_CTX_free(pkey_ctx) - } EVP_DigestSignInit(md_ctx, &pkey_ctx, .make(optional: md), nil, evp_key) // Now that Init has initialized pkey_ctx, set the padding option @@ -875,9 +872,6 @@ public class CryptorRSA { // Provide a pkey_ctx to EVP_DigestSignInit so that the EVP_PKEY_CTX of the signing operation // is written to it, to allow alternative signing options to be set var pkey_ctx = EVP_PKEY_CTX_new(evp_key, nil) - defer { - EVP_PKEY_CTX_free(pkey_ctx) - } EVP_DigestVerifyInit(md_ctx, &pkey_ctx, .make(optional: md), nil, evp_key) // Now that EVP_DigestVerifyInit has initialized pkey_ctx, set the padding option diff --git a/Sources/CryptorRSA/CryptorRSAKey.swift b/Sources/CryptorRSA/CryptorRSAKey.swift index 183d0ce..a10f2d9 100644 --- a/Sources/CryptorRSA/CryptorRSAKey.swift +++ b/Sources/CryptorRSA/CryptorRSAKey.swift @@ -610,9 +610,9 @@ extension CryptorRSA { #if os(Linux) var publicKeyBytes: Data? - deinit { - RSA_free(reference) - } +// deinit { +// RSA_free(.make(optional: reference)) +// } #endif /// Represents the type of key data contained. From 44160618f406cc4d0deb4fedad1feefc386e76e3 Mon Sep 17 00:00:00 2001 From: andy Date: Mon, 25 Feb 2019 15:48:49 +0000 Subject: [PATCH 04/11] Added rsa Free --- Sources/CryptorRSA/CryptorRSAKey.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Sources/CryptorRSA/CryptorRSAKey.swift b/Sources/CryptorRSA/CryptorRSAKey.swift index a10f2d9..8e6fb99 100644 --- a/Sources/CryptorRSA/CryptorRSAKey.swift +++ b/Sources/CryptorRSA/CryptorRSAKey.swift @@ -610,9 +610,9 @@ extension CryptorRSA { #if os(Linux) var publicKeyBytes: Data? -// deinit { -// RSA_free(.make(optional: reference)) -// } + deinit { + RSA_free(.make(optional: reference)) + } #endif /// Represents the type of key data contained. From e5d5fd8cba6fc24a83415c29ade6afa57ebbbaf0 Mon Sep 17 00:00:00 2001 From: andy Date: Mon, 25 Feb 2019 17:04:14 +0000 Subject: [PATCH 05/11] Use evp for native key --- Sources/CryptorRSA/CryptorRSA.swift | 275 +++++++++--------- Sources/CryptorRSA/CryptorRSADigest.swift | 192 ++++++------- Sources/CryptorRSA/CryptorRSAKey.swift | 277 +++++++++---------- Sources/CryptorRSA/CryptorRSAUtilities.swift | 80 +++--- Tests/CryptorRSATests/CryptorRSATests.swift | 26 +- 5 files changed, 417 insertions(+), 433 deletions(-) diff --git a/Sources/CryptorRSA/CryptorRSA.swift b/Sources/CryptorRSA/CryptorRSA.swift index 78e99c7..2a44d24 100644 --- a/Sources/CryptorRSA/CryptorRSA.swift +++ b/Sources/CryptorRSA/CryptorRSA.swift @@ -221,7 +221,7 @@ public class CryptorRSA { throw Error(code: CryptorRSA.ERR_KEY_NOT_PUBLIC, reason: "Supplied key is not public") } - #if os(Linux) + #if os(Linux) switch algorithm { case .gcm: return try encryptedGCM(with: key) @@ -229,23 +229,23 @@ public class CryptorRSA { // Same algorithm is used regardless of sha return try encryptedCBC(with: key) } - #else - - var response: Unmanaged? = nil - let eData = SecKeyCreateEncryptedData(key.reference, algorithm.alogrithmForEncryption, self.data as CFData, &response) - if response != nil { - - guard let error = response?.takeRetainedValue() else { - - throw Error(code: CryptorRSA.ERR_ENCRYPTION_FAILED, reason: "Encryption failed. Unable to determine error.") - } - - throw Error(code: CryptorRSA.ERR_ENCRYPTION_FAILED, reason: "Encryption failed with error: \(error)") - } - - return EncryptedData(with: eData! as Data) + #else + + var response: Unmanaged? = nil + let eData = SecKeyCreateEncryptedData(key.reference, algorithm.alogrithmForEncryption, self.data as CFData, &response) + if response != nil { + + guard let error = response?.takeRetainedValue() else { + + throw Error(code: CryptorRSA.ERR_ENCRYPTION_FAILED, reason: "Encryption failed. Unable to determine error.") + } + + throw Error(code: CryptorRSA.ERR_ENCRYPTION_FAILED, reason: "Encryption failed with error: \(error)") + } + + return EncryptedData(with: eData! as Data) - #endif + #endif } /// @@ -271,7 +271,7 @@ public class CryptorRSA { throw Error(code: CryptorRSA.ERR_KEY_NOT_PUBLIC, reason: "Supplied key is not private") } - #if os(Linux) + #if os(Linux) switch algorithm { case .gcm: @@ -281,23 +281,23 @@ public class CryptorRSA { return try decryptedCBC(with: key) } - #else - - var response: Unmanaged? = nil - let pData = SecKeyCreateDecryptedData(key.reference, algorithm.alogrithmForEncryption, self.data as CFData, &response) - if response != nil { - - guard let error = response?.takeRetainedValue() else { - - throw Error(code: CryptorRSA.ERR_DECRYPTION_FAILED, reason: "Decryption failed. Unable to determine error.") - } - - throw Error(code: CryptorRSA.ERR_DECRYPTION_FAILED, reason: "Decryption failed with error: \(error)") - } - - return PlaintextData(with: pData! as Data) - - #endif + #else + + var response: Unmanaged? = nil + let pData = SecKeyCreateDecryptedData(key.reference, algorithm.alogrithmForEncryption, self.data as CFData, &response) + if response != nil { + + guard let error = response?.takeRetainedValue() else { + + throw Error(code: CryptorRSA.ERR_DECRYPTION_FAILED, reason: "Decryption failed. Unable to determine error.") + } + + throw Error(code: CryptorRSA.ERR_DECRYPTION_FAILED, reason: "Decryption failed with error: \(error)") + } + + return PlaintextData(with: pData! as Data) + + #endif } /// @@ -309,6 +309,18 @@ public class CryptorRSA { let rsaEncryptCtx = EVP_CIPHER_CTX_new_wrapper() EVP_CIPHER_CTX_init_wrapper(rsaEncryptCtx) + // get rsaKey + guard let rsaKey = EVP_PKEY_get1_RSA(.make(optional: key.reference)) else { + let source = "Couldn't create key reference from key data" + if let reason = CryptorRSA.getLastError(source: source) { + throw Error(code: ERR_ADD_KEY, reason: reason) + } + throw Error(code: ERR_ADD_KEY, reason: source + ": No OpenSSL error reported.") + } + defer { + RSA_free(rsaKey) + } + // Set the additional authenticated data (aad) as the RSA key modulus and publicExponent in an ASN1 sequence. guard let aad = key.publicKeyBytes else { let source = "Encryption failed" @@ -368,7 +380,7 @@ public class CryptorRSA { // Set the aeskey and iv for the symmetric encryption. EVP_EncryptInit_ex(rsaEncryptCtx, nil, nil, aeskey, iv) == 1, // Encrypt the aes key using the rsa public key with SHA1, OAEP padding. - RSA_public_encrypt(Int32(keySize), aeskey, encryptedKey, .make(optional: key.reference), RSA_PKCS1_OAEP_PADDING) == encryptedCapacity, + RSA_public_encrypt(Int32(keySize), aeskey, encryptedKey, .make(optional: rsaKey), RSA_PKCS1_OAEP_PADDING) == encryptedCapacity, // Add the aad to the encryption context. // This is used in generating the GCM tag. We don't use this processedLength. EVP_EncryptUpdate(rsaEncryptCtx, nil, &processedLength, [UInt8](aad), Int32(aad.count)) == 1 @@ -418,16 +430,7 @@ public class CryptorRSA { func encryptedCBC(with key: PublicKey) throws -> EncryptedData? { // Convert RSA key to EVP - var evp_key = EVP_PKEY_new() - var rc = EVP_PKEY_set1_RSA(evp_key, .make(optional: key.reference)) - guard rc == 1 else { - let source = "Couldn't create key reference from key data" - if let reason = CryptorRSA.getLastError(source: source) { - - throw Error(code: ERR_ADD_KEY, reason: reason) - } - throw Error(code: ERR_ADD_KEY, reason: source + ": No OpenSSL error reported.") - } + var evp_key: UnsafeMutablePointer? = .make(optional: key.reference) // TODO: hash type option is not being used right now. let enc = EVP_aes_256_cbc() @@ -438,7 +441,6 @@ public class CryptorRSA { defer { EVP_CIPHER_CTX_reset_wrapper(rsaEncryptCtx) EVP_CIPHER_CTX_free_wrapper(rsaEncryptCtx) - EVP_PKEY_free(evp_key) } EVP_CIPHER_CTX_set_padding(rsaEncryptCtx, padding) @@ -446,7 +448,7 @@ public class CryptorRSA { // Initialize the AES encryption key array (of size 1) typealias UInt8Ptr = UnsafeMutablePointer? var ek: UInt8Ptr - ek = UnsafeMutablePointer.allocate(capacity: Int(EVP_PKEY_size(evp_key))) + ek = UnsafeMutablePointer.allocate(capacity: Int(EVP_PKEY_size(.make(optional: key.reference)))) let ekPtr = UnsafeMutablePointer.allocate(capacity: MemoryLayout.size) ekPtr.pointee = ek @@ -518,6 +520,18 @@ public class CryptorRSA { let rsaDecryptCtx = EVP_CIPHER_CTX_new() EVP_CIPHER_CTX_init_wrapper(rsaDecryptCtx) + // get rsaKey + guard let rsaKey = EVP_PKEY_get1_RSA(.make(optional: key.reference)) else { + let source = "Couldn't create key reference from key data" + if let reason = CryptorRSA.getLastError(source: source) { + throw Error(code: ERR_ADD_KEY, reason: reason) + } + throw Error(code: ERR_ADD_KEY, reason: source + ": No OpenSSL error reported.") + } + defer { + RSA_free(rsaKey) + } + // Set the additional authenticated data (aad) as the RSA key modulus and publicExponent in an ASN1 sequence. guard let aad = key.publicKeyBytes else { let source = "Encryption failed" @@ -571,7 +585,7 @@ public class CryptorRSA { let iv = [UInt8](repeating: 0, count: 16) // Decrypt the encryptedKey into the aeskey using the RSA private key - guard RSA_private_decrypt(Int32(encryptedKey.count), [UInt8](encryptedKey), aeskey, .make(optional: key.reference), RSA_PKCS1_OAEP_PADDING) != 0, + guard RSA_private_decrypt(Int32(encryptedKey.count), [UInt8](encryptedKey), aeskey, rsaKey, RSA_PKCS1_OAEP_PADDING) != 0, // Set the IV length to be 16 bytes. EVP_CIPHER_CTX_ctrl(rsaDecryptCtx, EVP_CTRL_GCM_SET_IVLEN, 16, nil) == 1, // Set the AES key to be 16 bytes. @@ -619,23 +633,23 @@ public class CryptorRSA { /// Decrypt the data using aes GCM for cross platform support. func decryptedCBC(with key: PrivateKey) throws -> PlaintextData? { // Convert RSA key to EVP - var evp_key = EVP_PKEY_new() - var status = EVP_PKEY_set1_RSA(evp_key, .make(optional: key.reference)) - guard status == 1 else { - let source = "Couldn't create key reference from key data" - if let reason = CryptorRSA.getLastError(source: source) { - - throw Error(code: ERR_ADD_KEY, reason: reason) - } - throw Error(code: ERR_ADD_KEY, reason: source + ": No OpenSSL error reported.") - } +// var evp_key = EVP_PKEY_new() +// var status = EVP_PKEY_set1_RSA(evp_key, .make(optional: key.reference)) +// guard status == 1 else { +// let source = "Couldn't create key reference from key data" +// if let reason = CryptorRSA.getLastError(source: source) { +// +// throw Error(code: ERR_ADD_KEY, reason: reason) +// } +// throw Error(code: ERR_ADD_KEY, reason: source + ": No OpenSSL error reported.") +// } // TODO: hash type option is not being used right now. let encType = EVP_aes_256_cbc() let padding = RSA_PKCS1_OAEP_PADDING // Size of symmetric encryption - let encKeyLength = Int(EVP_PKEY_size(evp_key)) + let encKeyLength = Int(EVP_PKEY_size(.make(optional: key.reference))) // Size of the corresponding cipher's IV let encIVLength = Int(EVP_CIPHER_iv_length(.make(optional: encType))) // Size of encryptedKey @@ -652,7 +666,6 @@ public class CryptorRSA { defer { EVP_CIPHER_CTX_reset_wrapper(rsaDecryptCtx) EVP_CIPHER_CTX_free_wrapper(rsaDecryptCtx) - EVP_PKEY_free(evp_key) } EVP_CIPHER_CTX_set_padding(rsaDecryptCtx, padding) @@ -671,9 +684,9 @@ public class CryptorRSA { #endif } // EVP_OpenInit returns 0 on error or the recovered secret key size if successful - status = encryptedKey.withUnsafeBytes({ (ek: UnsafePointer) -> Int32 in + var status = encryptedKey.withUnsafeBytes({ (ek: UnsafePointer) -> Int32 in return encryptedIV.withUnsafeBytes({ (iv: UnsafePointer) -> Int32 in - return EVP_OpenInit(rsaDecryptCtx, .make(optional: encType), ek, Int32(encryptedKey.count), iv, evp_key) + return EVP_OpenInit(rsaDecryptCtx, .make(optional: encType), ek, Int32(encryptedKey.count), iv, .make(optional: key.reference)) }) }) guard status != 0 else { @@ -733,7 +746,7 @@ public class CryptorRSA { throw Error(code: CryptorRSA.ERR_KEY_NOT_PRIVATE, reason: "Supplied key is not private") } - #if os(Linux) + #if os(Linux) let md_ctx = EVP_MD_CTX_new_wrapper() @@ -742,26 +755,26 @@ public class CryptorRSA { } // convert RSA key to EVP - let evp_key = EVP_PKEY_new() - defer { - EVP_PKEY_free(evp_key) - } - var rc = EVP_PKEY_set1_RSA(evp_key, .make(optional: key.reference)) - guard rc == 1 else { - let source = "Couldn't create key reference from key data" - if let reason = CryptorRSA.getLastError(source: source) { - - throw Error(code: ERR_ADD_KEY, reason: reason) - } - throw Error(code: ERR_ADD_KEY, reason: source + ": No OpenSSL error reported.") - } +// let evp_key = EVP_PKEY_new() +// defer { +// EVP_PKEY_free(evp_key) +// } +// var rc = EVP_PKEY_set1_RSA(evp_key, .make(optional: key.reference)) +// guard rc == 1 else { +// let source = "Couldn't create key reference from key data" +// if let reason = CryptorRSA.getLastError(source: source) { +// +// throw Error(code: ERR_ADD_KEY, reason: reason) +// } +// throw Error(code: ERR_ADD_KEY, reason: source + ": No OpenSSL error reported.") +// } let (md, padding) = algorithm.algorithmForSignature // Provide a pkey_ctx to EVP_DigestSignInit so that the EVP_PKEY_CTX of the signing operation // is written to it, to allow alternative signing options to be set - var pkey_ctx = EVP_PKEY_CTX_new(evp_key, nil) - EVP_DigestSignInit(md_ctx, &pkey_ctx, .make(optional: md), nil, evp_key) + var pkey_ctx = EVP_PKEY_CTX_new(.make(optional: key.reference), nil) + EVP_DigestSignInit(md_ctx, &pkey_ctx, .make(optional: md), nil, .make(optional: key.reference)) // Now that Init has initialized pkey_ctx, set the padding option EVP_PKEY_CTX_ctrl(pkey_ctx, EVP_PKEY_RSA, -1, EVP_PKEY_CTRL_RSA_PADDING, padding, nil) @@ -784,7 +797,7 @@ public class CryptorRSA { #endif } - rc = EVP_DigestSignFinal(md_ctx, sig, &sig_len) + let rc = EVP_DigestSignFinal(md_ctx, sig, &sig_len) guard rc == 1, sig_len > 0 else { let source = "Signing failed." if let reason = CryptorRSA.getLastError(source: source) { @@ -796,23 +809,23 @@ public class CryptorRSA { return SignedData(with: Data(bytes: sig, count: sig_len)) - #else - - var response: Unmanaged? = nil - let sData = SecKeyCreateSignature(key.reference, algorithm.algorithmForSignature, self.data as CFData, &response) - if response != nil { - - guard let error = response?.takeRetainedValue() else { - - throw Error(code: CryptorRSA.ERR_SIGNING_FAILED, reason: "Signing failed. Unable to determine error.") - } - - throw Error(code: CryptorRSA.ERR_SIGNING_FAILED, reason: "Signing failed with error: \(error)") - } - - return SignedData(with: sData! as Data) - - #endif + #else + + var response: Unmanaged? = nil + let sData = SecKeyCreateSignature(key.reference, algorithm.algorithmForSignature, self.data as CFData, &response) + if response != nil { + + guard let error = response?.takeRetainedValue() else { + + throw Error(code: CryptorRSA.ERR_SIGNING_FAILED, reason: "Signing failed. Unable to determine error.") + } + + throw Error(code: CryptorRSA.ERR_SIGNING_FAILED, reason: "Signing failed with error: \(error)") + } + + return SignedData(with: sData! as Data) + + #endif } /// @@ -844,7 +857,7 @@ public class CryptorRSA { throw Error(code: CryptorRSA.ERR_NOT_SIGNED_DATA, reason: "Supplied signature is not of signed data type") } - #if os(Linux) + #if os(Linux) let md_ctx = EVP_MD_CTX_new_wrapper() @@ -853,31 +866,31 @@ public class CryptorRSA { } // convert RSA key to EVP - let evp_key = EVP_PKEY_new() - defer { - EVP_PKEY_free(evp_key) - } - var rc = EVP_PKEY_set1_RSA(evp_key, .make(optional: key.reference)) - guard rc == 1 else { - let source = "Couldn't create key reference from key data" - if let reason = CryptorRSA.getLastError(source: source) { - - throw Error(code: ERR_ADD_KEY, reason: reason) - } - throw Error(code: ERR_ADD_KEY, reason: source + ": No OpenSSL error reported.") - } +// let evp_key = EVP_PKEY_new() +// defer { +// EVP_PKEY_free(evp_key) +// } +// var rc = EVP_PKEY_set1_RSA(evp_key, .make(optional: key.reference)) +// guard rc == 1 else { +// let source = "Couldn't create key reference from key data" +// if let reason = CryptorRSA.getLastError(source: source) { +// +// throw Error(code: ERR_ADD_KEY, reason: reason) +// } +// throw Error(code: ERR_ADD_KEY, reason: source + ": No OpenSSL error reported.") +// } let (md, padding) = algorithm.algorithmForSignature // Provide a pkey_ctx to EVP_DigestSignInit so that the EVP_PKEY_CTX of the signing operation // is written to it, to allow alternative signing options to be set - var pkey_ctx = EVP_PKEY_CTX_new(evp_key, nil) - EVP_DigestVerifyInit(md_ctx, &pkey_ctx, .make(optional: md), nil, evp_key) + var pkey_ctx = EVP_PKEY_CTX_new(.make(optional: key.reference), nil) + EVP_DigestVerifyInit(md_ctx, &pkey_ctx, .make(optional: md), nil, .make(optional: key.reference)) // Now that EVP_DigestVerifyInit has initialized pkey_ctx, set the padding option EVP_PKEY_CTX_ctrl(pkey_ctx, EVP_PKEY_RSA, -1, EVP_PKEY_CTRL_RSA_PADDING, padding, nil) - rc = self.data.withUnsafeBytes({ (message: UnsafePointer) -> Int32 in + var rc = self.data.withUnsafeBytes({ (message: UnsafePointer) -> Int32 in return EVP_DigestUpdate(md_ctx, message, self.data.count) }) guard rc == 1 else { @@ -899,23 +912,23 @@ public class CryptorRSA { return (rc == 1) ? true : false - #else - - var response: Unmanaged? = nil - let result = SecKeyVerifySignature(key.reference, algorithm.algorithmForSignature, self.data as CFData, signature.data as CFData, &response) - if response != nil { - - guard let error = response?.takeRetainedValue() else { - - throw Error(code: CryptorRSA.ERR_VERIFICATION_FAILED, reason: "Signature verification failed. Unable to determine error.") - } - - throw Error(code: CryptorRSA.ERR_VERIFICATION_FAILED, reason: "Signature verification failed with error: \(error)") - } - - return result - - #endif + #else + + var response: Unmanaged? = nil + let result = SecKeyVerifySignature(key.reference, algorithm.algorithmForSignature, self.data as CFData, signature.data as CFData, &response) + if response != nil { + + guard let error = response?.takeRetainedValue() else { + + throw Error(code: CryptorRSA.ERR_VERIFICATION_FAILED, reason: "Signature verification failed. Unable to determine error.") + } + + throw Error(code: CryptorRSA.ERR_VERIFICATION_FAILED, reason: "Signature verification failed with error: \(error)") + } + + return result + + #endif } // MARK: --- Utility diff --git a/Sources/CryptorRSA/CryptorRSADigest.swift b/Sources/CryptorRSA/CryptorRSADigest.swift index 8a1dd97..a0a421b 100644 --- a/Sources/CryptorRSA/CryptorRSADigest.swift +++ b/Sources/CryptorRSA/CryptorRSADigest.swift @@ -19,7 +19,7 @@ // #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) - import CommonCrypto + import CommonCrypto #elseif os(Linux) import OpenSSL public typealias CC_LONG = size_t @@ -63,7 +63,7 @@ extension Data { /// Digest Length public var length: CC_LONG { - #if os(Linux) + #if os(Linux) switch self { @@ -86,33 +86,33 @@ extension Data { return CC_LONG(SHA_DIGEST_LENGTH) } - #else + #else - switch self { - - case .sha1: - return CC_LONG(CC_SHA1_DIGEST_LENGTH) - - case .sha224: - return CC_LONG(CC_SHA224_DIGEST_LENGTH) - - case .sha256: - return CC_LONG(CC_SHA256_DIGEST_LENGTH) - - case .sha384: - return CC_LONG(CC_SHA384_DIGEST_LENGTH) - - case .sha512: - return CC_LONG(CC_SHA512_DIGEST_LENGTH) - + switch self { + + case .sha1: + return CC_LONG(CC_SHA1_DIGEST_LENGTH) + + case .sha224: + return CC_LONG(CC_SHA224_DIGEST_LENGTH) + + case .sha256: + return CC_LONG(CC_SHA256_DIGEST_LENGTH) + + case .sha384: + return CC_LONG(CC_SHA384_DIGEST_LENGTH) + + case .sha512: + return CC_LONG(CC_SHA512_DIGEST_LENGTH) + case .gcm: return CC_LONG(CC_SHA1_DIGEST_LENGTH) - } + } - #endif + #endif } - #if os(Linux) + #if os(Linux) // Hash, padding type public var algorithmForSignature: (OpaquePointer?, Int32) { @@ -167,63 +167,63 @@ extension Data { } #else - - @available(macOS 10.12, iOS 10.0, *) - public var algorithmForSignature: SecKeyAlgorithm { - - switch self { - - case .sha1: - return .rsaSignatureMessagePKCS1v15SHA1 - - case .sha224: - return .rsaSignatureMessagePKCS1v15SHA224 - - case .sha256: - return .rsaSignatureMessagePKCS1v15SHA256 - - case .sha384: - return .rsaSignatureMessagePKCS1v15SHA384 - - case .sha512: - return .rsaSignatureMessagePKCS1v15SHA512 + + @available(macOS 10.12, iOS 10.0, *) + public var algorithmForSignature: SecKeyAlgorithm { + + switch self { + + case .sha1: + return .rsaSignatureMessagePKCS1v15SHA1 + + case .sha224: + return .rsaSignatureMessagePKCS1v15SHA224 + + case .sha256: + return .rsaSignatureMessagePKCS1v15SHA256 + + case .sha384: + return .rsaSignatureMessagePKCS1v15SHA384 + + case .sha512: + return .rsaSignatureMessagePKCS1v15SHA512 case .gcm: return .rsaSignatureMessagePKCS1v15SHA1 - } - } - - @available(macOS 10.12, iOS 10.0, *) - public var alogrithmForEncryption: SecKeyAlgorithm { - - switch self { - - case .sha1: - return .rsaEncryptionOAEPSHA1AESGCM - - case .sha224: - return .rsaEncryptionOAEPSHA224AESGCM - - case .sha256: - return .rsaEncryptionOAEPSHA256AESGCM - - case .sha384: - return .rsaEncryptionOAEPSHA384AESGCM - - case .sha512: - return .rsaEncryptionOAEPSHA512AESGCM + } + } + + @available(macOS 10.12, iOS 10.0, *) + public var alogrithmForEncryption: SecKeyAlgorithm { + + switch self { + + case .sha1: + return .rsaEncryptionOAEPSHA1AESGCM + + case .sha224: + return .rsaEncryptionOAEPSHA224AESGCM + + case .sha256: + return .rsaEncryptionOAEPSHA256AESGCM + + case .sha384: + return .rsaEncryptionOAEPSHA384AESGCM + + case .sha512: + return .rsaEncryptionOAEPSHA512AESGCM case .gcm: return .rsaEncryptionOAEPSHA1AESGCM - - } - } - - #endif + + } + } + + #endif /// The platform/alogorithm dependent function to be used. /// (UnsafePointer!, Int, UnsafeMutablePointer!) -> UnsafeMutablePointer! - #if os(Linux) + #if os(Linux) public var engine: (_ data: UnsafePointer, _ len: CC_LONG, _ md: UnsafeMutablePointer) -> UnsafeMutablePointer? { @@ -250,33 +250,33 @@ extension Data { } } - #else - - public var engine: (_ data: UnsafeRawPointer, _ len: CC_LONG, _ md: UnsafeMutablePointer) -> UnsafeMutablePointer? { - - switch self { - - case .sha1: - return CC_SHA1 - - case .sha224: - return CC_SHA224 - - case .sha256: - return CC_SHA256 - - case .sha384: - return CC_SHA384 - - case .sha512: - return CC_SHA512 - + #else + + public var engine: (_ data: UnsafeRawPointer, _ len: CC_LONG, _ md: UnsafeMutablePointer) -> UnsafeMutablePointer? { + + switch self { + + case .sha1: + return CC_SHA1 + + case .sha224: + return CC_SHA224 + + case .sha256: + return CC_SHA256 + + case .sha384: + return CC_SHA384 + + case .sha512: + return CC_SHA512 + case .gcm: return CC_SHA1 - } - } - - #endif + } + } + + #endif } diff --git a/Sources/CryptorRSA/CryptorRSAKey.swift b/Sources/CryptorRSA/CryptorRSAKey.swift index 8e6fb99..7fd7937 100644 --- a/Sources/CryptorRSA/CryptorRSAKey.swift +++ b/Sources/CryptorRSA/CryptorRSAKey.swift @@ -20,7 +20,7 @@ // #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) - import CommonCrypto + import CommonCrypto #elseif os(Linux) import OpenSSL #endif @@ -34,15 +34,15 @@ extension CryptorRSA { // MARK: Type Aliases - #if os(Linux) + #if os(Linux) public typealias NativeKey = OpaquePointer? - #else - - public typealias NativeKey = SecKey - - #endif + #else + + public typealias NativeKey = SecKey + + #endif // MARK: Class Functions @@ -58,11 +58,11 @@ extension CryptorRSA { /// public class func createPublicKey(with data: Data) throws -> PublicKey { - #if os(Linux) + #if os(Linux) let data = CryptorRSA.convertDerToPem(from: data, type: .publicType) - #endif + #endif return try PublicKey(with: data) } @@ -112,12 +112,12 @@ extension CryptorRSA { throw Error(code: ERR_INIT_PK, reason: "Couldn't decode base64 string") } - #if os(Linux) + #if os(Linux) // OpenSSL uses the PEM version when importing key... data = CryptorRSA.convertDerToPem(from: data, type: .publicType) - #endif + #endif return try PublicKey(with: data) } @@ -132,21 +132,21 @@ extension CryptorRSA { /// public class func createPublicKey(withPEM pemString: String) throws -> PublicKey { - #if os(Linux) + #if os(Linux) // OpenSSL takes the full PEM format... let keyData = pemString.data(using: String.Encoding.utf8)! return try PublicKey(with: keyData) - #else - - // Get the Base64 representation of the PEM encoded string after stripping off the PEM markers - let base64String = try CryptorRSA.base64String(for: pemString) - - return try createPublicKey(withBase64: base64String) - - #endif + #else + + // Get the Base64 representation of the PEM encoded string after stripping off the PEM markers + let base64String = try CryptorRSA.base64String(for: pemString) + + return try createPublicKey(withBase64: base64String) + + #endif } /// @@ -194,15 +194,15 @@ extension CryptorRSA { let dataIn = try Data(contentsOf: fullPath) - #if os(Linux) + #if os(Linux) let data = CryptorRSA.convertDerToPem(from: dataIn, type: .publicType) - #else - - let data = dataIn - - #endif + #else + + let data = dataIn + + #endif return try PublicKey(with: data) } @@ -227,19 +227,19 @@ extension CryptorRSA { let fullPath = URL(fileURLWithPath: #file).appendingPathComponent( path.appending(certNameFull) ).standardized // Import the data from the file... - #if os(Linux) + #if os(Linux) // In OpenSSL, we can just get the data and don't have to worry about stripping off headers etc. let data = try Data(contentsOf: fullPath) - #else - - // Get the Base64 representation of the PEM encoded string after stripping off the PEM markers... - let tmp = try String(contentsOf: fullPath, encoding: .utf8) - let base64 = try CryptorRSA.base64String(for: tmp) - let data = Data(base64Encoded: base64)! - - #endif + #else + + // Get the Base64 representation of the PEM encoded string after stripping off the PEM markers... + let tmp = try String(contentsOf: fullPath, encoding: .utf8) + let base64 = try CryptorRSA.base64String(for: tmp) + let data = Data(base64Encoded: base64)! + + #endif return try CryptorRSA.createPublicKey(data: data) } @@ -283,15 +283,15 @@ extension CryptorRSA { let dataIn = try Data(contentsOf: URL(fileURLWithPath: path)) - #if os(Linux) + #if os(Linux) let data = CryptorRSA.convertDerToPem(from: dataIn, type: .publicType) - #else - - let data = dataIn - - #endif + #else + + let data = dataIn + + #endif return try PublicKey(with: data) } @@ -331,7 +331,7 @@ extension CryptorRSA { /// internal class func createPublicKey(data: Data) throws -> PublicKey { - #if os(Linux) + #if os(Linux) let certbio = BIO_new(BIO_s_mem()) defer { @@ -367,53 +367,40 @@ extension CryptorRSA { throw Error(code: ERR_CREATE_CERT_FAILED, reason: "Error getting public key from certificate") } - let key = EVP_PKEY_get1_RSA( evp_key) - if key == nil { - throw Error(code: ERR_CREATE_CERT_FAILED, reason: "Error getting public key from certificate") - } - defer { - // RSA_free(key) - EVP_PKEY_free(evp_key) - } - - #if swift(>=4.1) - return PublicKey(with: .make(optional: key!)!) - #else - return PublicKey(with: key!) - #endif + return PublicKey(with: .make(optional: evp_key)!) - #else - - // Create a DER-encoded X.509 certificate object from the DER data... - let certificateData = SecCertificateCreateWithData(nil, data as CFData) - guard let certData = certificateData else { - - throw Error(code: ERR_CREATE_CERT_FAILED, reason: "Unable to create certificate from certificate data.") - } - - #if os(macOS) - - // Now extract the public key from it... - var key: SecKey? = nil - let status: OSStatus = withUnsafeMutablePointer(to: &key) { ptr in - - // Retrieves the public key from a certificate... - SecCertificateCopyPublicKey(certData, UnsafeMutablePointer(ptr)) - } - if status != errSecSuccess || key == nil { - - throw Error(code: ERR_EXTRACT_PUBLIC_KEY_FAILED, reason: "Unable to extract public key from data.") - } - - #else - - let key = SecCertificateCopyPublicKey(certData) - - #endif - - return PublicKey(with: key!) - - #endif + #else + + // Create a DER-encoded X.509 certificate object from the DER data... + let certificateData = SecCertificateCreateWithData(nil, data as CFData) + guard let certData = certificateData else { + + throw Error(code: ERR_CREATE_CERT_FAILED, reason: "Unable to create certificate from certificate data.") + } + + #if os(macOS) + + // Now extract the public key from it... + var key: SecKey? = nil + let status: OSStatus = withUnsafeMutablePointer(to: &key) { ptr in + + // Retrieves the public key from a certificate... + SecCertificateCopyPublicKey(certData, UnsafeMutablePointer(ptr)) + } + if status != errSecSuccess || key == nil { + + throw Error(code: ERR_EXTRACT_PUBLIC_KEY_FAILED, reason: "Unable to extract public key from data.") + } + + #else + + let key = SecCertificateCopyPublicKey(certData) + + #endif + + return PublicKey(with: key!) + + #endif } // MARK: -- Private Key Creation @@ -459,21 +446,21 @@ extension CryptorRSA { /// public class func createPrivateKey(withPEM pemString: String) throws -> PrivateKey { - #if os(Linux) + #if os(Linux) // OpenSSL takes the full PEM format... let keyData = pemString.data(using: String.Encoding.utf8)! return try PrivateKey(with: keyData) - #else - - // SecKey needs the PEM format stripped of the header info and converted to base64... - let base64String = try CryptorRSA.base64String(for: pemString) - - return try CryptorRSA.createPrivateKey(withBase64: base64String) - - #endif + #else + + // SecKey needs the PEM format stripped of the header info and converted to base64... + let base64String = try CryptorRSA.base64String(for: pemString) + + return try CryptorRSA.createPrivateKey(withBase64: base64String) + + #endif } /// @@ -519,16 +506,16 @@ extension CryptorRSA { let dataIn = try Data(contentsOf: fullPath) - #if os(Linux) + #if os(Linux) let data = CryptorRSA.convertDerToPem(from: dataIn, type: .privateType) - #else - - let data = dataIn - - #endif - + #else + + let data = dataIn + + #endif + return try PrivateKey(with: data) } @@ -571,15 +558,15 @@ extension CryptorRSA { let dataIn = try Data(contentsOf: URL(fileURLWithPath: path)) - #if os(Linux) + #if os(Linux) let data = CryptorRSA.convertDerToPem(from: dataIn, type: .privateType) - #else - - let data = dataIn - - #endif + #else + + let data = dataIn + + #endif return try PrivateKey(with: data) } @@ -611,7 +598,7 @@ extension CryptorRSA { #if os(Linux) var publicKeyBytes: Data? deinit { - RSA_free(.make(optional: reference)) + EVP_PKEY_free(.make(optional: reference)) } #endif @@ -675,24 +662,24 @@ extension CryptorRSA { self.reference = nativeKey } - #if os(Linux) && !swift(>=4.1) - - /// - /// Create a key using a native key. - /// - /// - Parameters: - /// - nativeKey: Pointer to RSA key structure. - /// - type: Type of key. - /// - /// - Returns: New `RSAKey` instance. - /// - internal init(with nativeKey: UnsafeMutablePointer, type: KeyType) { - - self.type = type - self.reference = .make(optional: nativeKey) - } - - #endif + #if os(Linux) && !swift(>=4.1) + + /// + /// Create a key using a native key. + /// + /// - Parameters: + /// - nativeKey: Pointer to RSA key structure. + /// - type: Type of key. + /// + /// - Returns: New `RSAKey` instance. + /// + internal init(with nativeKey: UnsafeMutablePointer, type: KeyType) { + + self.type = type + self.reference = .make(optional: nativeKey) + } + + #endif } // MARK: - @@ -804,22 +791,22 @@ extension CryptorRSA { super.init(with: nativeKey, type: .publicType) } - #if os(Linux) && !swift(>=4.1) - - /// - /// Create a key using a native key. - /// - /// - Parameters: - /// - nativeKey: Pointer to RSA key structure. - /// - /// - Returns: New `RSAKey` instance. - /// - public init(with nativeKey: UnsafeMutablePointer) { - - super.init(with: nativeKey, type: .publicType) - } - - #endif + #if os(Linux) && !swift(>=4.1) + + /// + /// Create a key using a native key. + /// + /// - Parameters: + /// - nativeKey: Pointer to RSA key structure. + /// + /// - Returns: New `RSAKey` instance. + /// + public init(with nativeKey: UnsafeMutablePointer) { + + super.init(with: nativeKey, type: .publicType) + } + + #endif } // MARK: - diff --git a/Sources/CryptorRSA/CryptorRSAUtilities.swift b/Sources/CryptorRSA/CryptorRSAUtilities.swift index 1f4543f..da7736f 100644 --- a/Sources/CryptorRSA/CryptorRSAUtilities.swift +++ b/Sources/CryptorRSA/CryptorRSAUtilities.swift @@ -20,7 +20,7 @@ // #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) - import CommonCrypto + import CommonCrypto #elseif os(Linux) import OpenSSL #endif @@ -49,7 +49,6 @@ public extension CryptorRSA { static func createKey(from keyData: Data, type: CryptorRSA.RSAKey.KeyType) throws -> NativeKey { let keyData = keyData - // Create a memory BIO... let bio = BIO_new(BIO_s_mem()) @@ -74,10 +73,6 @@ public extension CryptorRSA { } var evp_key: OpaquePointer? - - defer { - EVP_PKEY_free(.make(optional: evp_key)) - } // Read in the key data and process depending on key type... if type == .publicType { @@ -88,18 +83,7 @@ public extension CryptorRSA { evp_key = .init(PEM_read_bio_PrivateKey(bio, nil, nil, nil)) } - - let key = EVP_PKEY_get1_RSA(.make(optional: evp_key)) - if key == nil { - let source = "Couldn't create key reference from key data" - if let reason = CryptorRSA.getLastError(source: source) { - - throw Error(code: ERR_ADD_KEY, reason: reason) - } - throw Error(code: ERR_ADD_KEY, reason: source + ": No OpenSSL error reported.") - } - - return .init(key!) + return evp_key } /// @@ -162,38 +146,38 @@ public extension CryptorRSA { } #else - - /// - /// Create a key from key data. - /// - /// - Parameters: - /// - keyData: `Data` representation of the key. - /// - type: Type of key data. - /// - /// - Returns: `SecKey` representation of the key. - /// - static func createKey(from keyData: Data, type: CryptorRSA.RSAKey.KeyType) throws -> NativeKey { - - var keyData = keyData + + /// + /// Create a key from key data. + /// + /// - Parameters: + /// - keyData: `Data` representation of the key. + /// - type: Type of key data. + /// + /// - Returns: `SecKey` representation of the key. + /// + static func createKey(from keyData: Data, type: CryptorRSA.RSAKey.KeyType) throws -> NativeKey { - let keyClass = type == .publicType ? kSecAttrKeyClassPublic : kSecAttrKeyClassPrivate - - let sizeInBits = keyData.count * MemoryLayout.size - let keyDict: [CFString: Any] = [ - kSecAttrKeyType: kSecAttrKeyTypeRSA, - kSecAttrKeyClass: keyClass, - kSecAttrKeySizeInBits: NSNumber(value: sizeInBits) - ] - - guard let key = SecKeyCreateWithData(keyData as CFData, keyDict as CFDictionary, nil) else { - - throw Error(code: ERR_ADD_KEY, reason: "Couldn't create key reference from key data") - } + var keyData = keyData - return key - - } - + let keyClass = type == .publicType ? kSecAttrKeyClassPublic : kSecAttrKeyClassPrivate + + let sizeInBits = keyData.count * MemoryLayout.size + let keyDict: [CFString: Any] = [ + kSecAttrKeyType: kSecAttrKeyTypeRSA, + kSecAttrKeyClass: keyClass, + kSecAttrKeySizeInBits: NSNumber(value: sizeInBits) + ] + + guard let key = SecKeyCreateWithData(keyData as CFData, keyDict as CFDictionary, nil) else { + + throw Error(code: ERR_ADD_KEY, reason: "Couldn't create key reference from key data") + } + + return key + + } + #endif /// diff --git a/Tests/CryptorRSATests/CryptorRSATests.swift b/Tests/CryptorRSATests/CryptorRSATests.swift index c3d3aa4..a5b5f91 100644 --- a/Tests/CryptorRSATests/CryptorRSATests.swift +++ b/Tests/CryptorRSATests/CryptorRSATests.swift @@ -99,7 +99,7 @@ class CryptorRSATests: XCTestCase { let data = try Data(contentsOf: filePath) let publicKey = try? CryptorRSA.createPublicKey(extractingFrom: data) XCTAssertNotNil(publicKey) - XCTAssertTrue(publicKey!.type == .publicType) + XCTAssertTrue(publicKey?.type == .publicType) } } @@ -113,7 +113,7 @@ class CryptorRSATests: XCTestCase { let data = try Data(contentsOf: filePath) let publicKey = try? CryptorRSA.createPublicKey(extractingFrom: data) XCTAssertNotNil(publicKey) - XCTAssertTrue(publicKey!.type == .publicType) + XCTAssertTrue(publicKey?.type == .publicType) } } @@ -203,17 +203,17 @@ class CryptorRSATests: XCTestCase { func test_publicKeysFromComplexPEMFileWorksCorrectly() { - guard let input = CryptorRSATests.pemKeyString(name: "multiple-keys-testcase") else { - XCTFail() - return - } - - let keys = CryptorRSA.PublicKey.publicKeys(withPEM: input) - XCTAssertEqual(keys.count, 9) - - for publicKey in keys { - XCTAssertTrue(publicKey.type == .publicType) - } +// guard let input = CryptorRSATests.pemKeyString(name: "multiple-keys-testcase") else { +// XCTFail() +// return +// } +// +// let keys = CryptorRSA.PublicKey.publicKeys(withPEM: input) +// XCTAssertEqual(keys.count, 9) +// +// for publicKey in keys { +// XCTAssertTrue(publicKey.type == .publicType) +// } } func test_publicKeysFromEmptyPEMFileReturnsEmptyArray() { From 0c73af2353d5d0c17f06dc46d85bbc362a3e2da5 Mon Sep 17 00:00:00 2001 From: andy Date: Tue, 26 Feb 2019 10:14:50 +0000 Subject: [PATCH 06/11] use make optional for evp_key --- Sources/CryptorRSA/CryptorRSA.swift | 46 ++------------------ Sources/CryptorRSA/CryptorRSAKey.swift | 4 +- Sources/CryptorRSA/CryptorRSAUtilities.swift | 8 ++-- 3 files changed, 9 insertions(+), 49 deletions(-) diff --git a/Sources/CryptorRSA/CryptorRSA.swift b/Sources/CryptorRSA/CryptorRSA.swift index 2a44d24..5ff2b09 100644 --- a/Sources/CryptorRSA/CryptorRSA.swift +++ b/Sources/CryptorRSA/CryptorRSA.swift @@ -430,7 +430,7 @@ public class CryptorRSA { func encryptedCBC(with key: PublicKey) throws -> EncryptedData? { // Convert RSA key to EVP - var evp_key: UnsafeMutablePointer? = .make(optional: key.reference) + var evp_key = key.reference // TODO: hash type option is not being used right now. let enc = EVP_aes_256_cbc() @@ -463,7 +463,7 @@ public class CryptorRSA { iv.deallocate() encrypted.deallocate() #else - ek?.deallocate(capacity: Int(EVP_PKEY_size(evp_key))) + ek?.deallocate(capacity: Int(EVP_PKEY_size(.make(optional: key.reference)))) ekPtr.deallocate(capacity: MemoryLayout.size) iv.deallocate(capacity: Int(IVLength)) encrypted.deallocate(capacity: self.data.count + Int(IVLength)) @@ -476,7 +476,7 @@ public class CryptorRSA { // Initializes a cipher context ctx for encryption with cipher type using a random secret key and IV. // The secret key is encrypted using the public key (evp_key can be an array of public keys) // Here we are using just 1 public key - var status = EVP_SealInit(rsaEncryptCtx, .make(optional: enc), ekPtr, &encKeyLength, iv, &evp_key, 1) + var status = EVP_SealInit(rsaEncryptCtx, .make(optional: enc), ekPtr, &encKeyLength, iv, .make(optional: &evp_key), 1) // SealInit should return the number of public keys that were input, here it is only 1 guard status == 1 else { @@ -633,18 +633,6 @@ public class CryptorRSA { /// Decrypt the data using aes GCM for cross platform support. func decryptedCBC(with key: PrivateKey) throws -> PlaintextData? { // Convert RSA key to EVP -// var evp_key = EVP_PKEY_new() -// var status = EVP_PKEY_set1_RSA(evp_key, .make(optional: key.reference)) -// guard status == 1 else { -// let source = "Couldn't create key reference from key data" -// if let reason = CryptorRSA.getLastError(source: source) { -// -// throw Error(code: ERR_ADD_KEY, reason: reason) -// } -// throw Error(code: ERR_ADD_KEY, reason: source + ": No OpenSSL error reported.") -// } - - // TODO: hash type option is not being used right now. let encType = EVP_aes_256_cbc() let padding = RSA_PKCS1_OAEP_PADDING @@ -754,20 +742,6 @@ public class CryptorRSA { EVP_MD_CTX_free_wrapper(md_ctx) } - // convert RSA key to EVP -// let evp_key = EVP_PKEY_new() -// defer { -// EVP_PKEY_free(evp_key) -// } -// var rc = EVP_PKEY_set1_RSA(evp_key, .make(optional: key.reference)) -// guard rc == 1 else { -// let source = "Couldn't create key reference from key data" -// if let reason = CryptorRSA.getLastError(source: source) { -// -// throw Error(code: ERR_ADD_KEY, reason: reason) -// } -// throw Error(code: ERR_ADD_KEY, reason: source + ": No OpenSSL error reported.") -// } let (md, padding) = algorithm.algorithmForSignature @@ -865,20 +839,6 @@ public class CryptorRSA { EVP_MD_CTX_free_wrapper(md_ctx) } - // convert RSA key to EVP -// let evp_key = EVP_PKEY_new() -// defer { -// EVP_PKEY_free(evp_key) -// } -// var rc = EVP_PKEY_set1_RSA(evp_key, .make(optional: key.reference)) -// guard rc == 1 else { -// let source = "Couldn't create key reference from key data" -// if let reason = CryptorRSA.getLastError(source: source) { -// -// throw Error(code: ERR_ADD_KEY, reason: reason) -// } -// throw Error(code: ERR_ADD_KEY, reason: source + ": No OpenSSL error reported.") -// } let (md, padding) = algorithm.algorithmForSignature diff --git a/Sources/CryptorRSA/CryptorRSAKey.swift b/Sources/CryptorRSA/CryptorRSAKey.swift index 7fd7937..223622e 100644 --- a/Sources/CryptorRSA/CryptorRSAKey.swift +++ b/Sources/CryptorRSA/CryptorRSAKey.swift @@ -362,12 +362,12 @@ extension CryptorRSA { } // Extract the certificate's public key data. - let evp_key = X509_get_pubkey(cert) + let evp_key: OpaquePointer? = .init(X509_get_pubkey(cert)) if evp_key == nil { throw Error(code: ERR_CREATE_CERT_FAILED, reason: "Error getting public key from certificate") } - return PublicKey(with: .make(optional: evp_key)!) + return PublicKey(with: evp_key) #else diff --git a/Sources/CryptorRSA/CryptorRSAUtilities.swift b/Sources/CryptorRSA/CryptorRSAUtilities.swift index da7736f..77b438c 100644 --- a/Sources/CryptorRSA/CryptorRSAUtilities.swift +++ b/Sources/CryptorRSA/CryptorRSAUtilities.swift @@ -72,18 +72,18 @@ public extension CryptorRSA { BIO_ctrl(bio, BIO_CTRL_FLUSH, 0, nil) } - var evp_key: OpaquePointer? + var evp_key = EVP_PKEY_new() // Read in the key data and process depending on key type... if type == .publicType { - evp_key = .init(PEM_read_bio_PUBKEY(bio, nil, nil, nil)) + PEM_read_bio_PUBKEY(bio, &evp_key, nil, nil) } else { - evp_key = .init(PEM_read_bio_PrivateKey(bio, nil, nil, nil)) + PEM_read_bio_PrivateKey(bio, &evp_key, nil, nil) } - return evp_key + return .make(optional: evp_key) } /// From 5d4b0b7ea9703dded363dc9361aaffbfa53417bb Mon Sep 17 00:00:00 2001 From: andy Date: Tue, 26 Feb 2019 10:47:35 +0000 Subject: [PATCH 07/11] Copy EVP key for encryption --- Sources/CryptorRSA/CryptorRSA.swift | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/Sources/CryptorRSA/CryptorRSA.swift b/Sources/CryptorRSA/CryptorRSA.swift index 5ff2b09..1fbdff3 100644 --- a/Sources/CryptorRSA/CryptorRSA.swift +++ b/Sources/CryptorRSA/CryptorRSA.swift @@ -429,8 +429,14 @@ public class CryptorRSA { } func encryptedCBC(with key: PublicKey) throws -> EncryptedData? { - // Convert RSA key to EVP - var evp_key = key.reference + // Copy the EVP Key + var evp_key = EVP_PKEY_new() + let rsa = EVP_PKEY_get1_RSA(.make(optional: key.reference)) + EVP_PKEY_set1_RSA(evp_key, rsa) + RSA_free(rsa) + defer { + EVP_PKEY_free(evp_key) + } // TODO: hash type option is not being used right now. let enc = EVP_aes_256_cbc() @@ -476,7 +482,7 @@ public class CryptorRSA { // Initializes a cipher context ctx for encryption with cipher type using a random secret key and IV. // The secret key is encrypted using the public key (evp_key can be an array of public keys) // Here we are using just 1 public key - var status = EVP_SealInit(rsaEncryptCtx, .make(optional: enc), ekPtr, &encKeyLength, iv, .make(optional: &evp_key), 1) + var status = EVP_SealInit(rsaEncryptCtx, .make(optional: enc), ekPtr, &encKeyLength, iv, &evp_key, 1) // SealInit should return the number of public keys that were input, here it is only 1 guard status == 1 else { @@ -519,7 +525,11 @@ public class CryptorRSA { // Initialize the decryption context. let rsaDecryptCtx = EVP_CIPHER_CTX_new() EVP_CIPHER_CTX_init_wrapper(rsaDecryptCtx) - + defer { + // On completion deallocate the memory + EVP_CIPHER_CTX_reset_wrapper(rsaDecryptCtx) + EVP_CIPHER_CTX_free_wrapper(rsaDecryptCtx) + } // get rsaKey guard let rsaKey = EVP_PKEY_get1_RSA(.make(optional: key.reference)) else { let source = "Couldn't create key reference from key data" @@ -568,7 +578,6 @@ public class CryptorRSA { let decrypted = UnsafeMutablePointer.allocate(capacity: Int(encryptedData.count + 16)) defer { // On completion deallocate the memory - EVP_CIPHER_CTX_free_wrapper(rsaDecryptCtx) #if swift(>=4.1) aeskey.deallocate() decrypted.deallocate() From 1d3f9187f66878c0a48294bf3bcf9275830f1a86 Mon Sep 17 00:00:00 2001 From: andy Date: Tue, 26 Feb 2019 12:11:06 +0000 Subject: [PATCH 08/11] Added ctx cleanup --- Sources/CryptorRSA/CryptorRSA.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Sources/CryptorRSA/CryptorRSA.swift b/Sources/CryptorRSA/CryptorRSA.swift index 1fbdff3..13ba8e6 100644 --- a/Sources/CryptorRSA/CryptorRSA.swift +++ b/Sources/CryptorRSA/CryptorRSA.swift @@ -748,6 +748,7 @@ public class CryptorRSA { let md_ctx = EVP_MD_CTX_new_wrapper() defer { + EVP_MD_CTX_cleanup(md_ctx) EVP_MD_CTX_free_wrapper(md_ctx) } @@ -845,6 +846,7 @@ public class CryptorRSA { let md_ctx = EVP_MD_CTX_new_wrapper() defer { + EVP_MD_CTX_cleanup(md_ctx) EVP_MD_CTX_free_wrapper(md_ctx) } From ac329da70e27cd3cb7140ae4f4c6e96f4a3b015f Mon Sep 17 00:00:00 2001 From: andy Date: Tue, 26 Feb 2019 15:51:14 +0000 Subject: [PATCH 09/11] remove padding ctx --- Sources/CryptorRSA/CryptorRSA.swift | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/Sources/CryptorRSA/CryptorRSA.swift b/Sources/CryptorRSA/CryptorRSA.swift index 13ba8e6..4eb7e11 100644 --- a/Sources/CryptorRSA/CryptorRSA.swift +++ b/Sources/CryptorRSA/CryptorRSA.swift @@ -748,20 +748,15 @@ public class CryptorRSA { let md_ctx = EVP_MD_CTX_new_wrapper() defer { - EVP_MD_CTX_cleanup(md_ctx) EVP_MD_CTX_free_wrapper(md_ctx) } - let (md, padding) = algorithm.algorithmForSignature + let (md, _) = algorithm.algorithmForSignature // Provide a pkey_ctx to EVP_DigestSignInit so that the EVP_PKEY_CTX of the signing operation // is written to it, to allow alternative signing options to be set - var pkey_ctx = EVP_PKEY_CTX_new(.make(optional: key.reference), nil) - EVP_DigestSignInit(md_ctx, &pkey_ctx, .make(optional: md), nil, .make(optional: key.reference)) - - // Now that Init has initialized pkey_ctx, set the padding option - EVP_PKEY_CTX_ctrl(pkey_ctx, EVP_PKEY_RSA, -1, EVP_PKEY_CTRL_RSA_PADDING, padding, nil) + EVP_DigestSignInit(md_ctx, nil, .make(optional: md), nil, .make(optional: key.reference)) // Convert Data to UnsafeRawPointer! _ = self.data.withUnsafeBytes({ (message: UnsafePointer) -> Int32 in @@ -846,20 +841,16 @@ public class CryptorRSA { let md_ctx = EVP_MD_CTX_new_wrapper() defer { - EVP_MD_CTX_cleanup(md_ctx) EVP_MD_CTX_free_wrapper(md_ctx) } - let (md, padding) = algorithm.algorithmForSignature + let (md, _) = algorithm.algorithmForSignature // Provide a pkey_ctx to EVP_DigestSignInit so that the EVP_PKEY_CTX of the signing operation // is written to it, to allow alternative signing options to be set - var pkey_ctx = EVP_PKEY_CTX_new(.make(optional: key.reference), nil) - EVP_DigestVerifyInit(md_ctx, &pkey_ctx, .make(optional: md), nil, .make(optional: key.reference)) + EVP_DigestVerifyInit(md_ctx, nil, .make(optional: md), nil, .make(optional: key.reference)) - // Now that EVP_DigestVerifyInit has initialized pkey_ctx, set the padding option - EVP_PKEY_CTX_ctrl(pkey_ctx, EVP_PKEY_RSA, -1, EVP_PKEY_CTRL_RSA_PADDING, padding, nil) var rc = self.data.withUnsafeBytes({ (message: UnsafePointer) -> Int32 in return EVP_DigestUpdate(md_ctx, message, self.data.count) From 7248cd9e5f9d12cd9cdef8d7e9c1107cc44598aa Mon Sep 17 00:00:00 2001 From: andy Date: Tue, 26 Feb 2019 16:35:16 +0000 Subject: [PATCH 10/11] fix whitespace changes --- Sources/CryptorRSA/CryptorRSA.swift | 166 +++++++------- Sources/CryptorRSA/CryptorRSADigest.swift | 196 ++++++++-------- Sources/CryptorRSA/CryptorRSAKey.swift | 224 +++++++++---------- Sources/CryptorRSA/CryptorRSAUtilities.swift | 72 +++--- Tests/CryptorRSATests/CryptorRSATests.swift | 22 +- 5 files changed, 340 insertions(+), 340 deletions(-) diff --git a/Sources/CryptorRSA/CryptorRSA.swift b/Sources/CryptorRSA/CryptorRSA.swift index 4eb7e11..d7156c8 100644 --- a/Sources/CryptorRSA/CryptorRSA.swift +++ b/Sources/CryptorRSA/CryptorRSA.swift @@ -221,7 +221,7 @@ public class CryptorRSA { throw Error(code: CryptorRSA.ERR_KEY_NOT_PUBLIC, reason: "Supplied key is not public") } - #if os(Linux) + #if os(Linux) switch algorithm { case .gcm: return try encryptedGCM(with: key) @@ -229,23 +229,23 @@ public class CryptorRSA { // Same algorithm is used regardless of sha return try encryptedCBC(with: key) } - #else - - var response: Unmanaged? = nil - let eData = SecKeyCreateEncryptedData(key.reference, algorithm.alogrithmForEncryption, self.data as CFData, &response) - if response != nil { - - guard let error = response?.takeRetainedValue() else { - - throw Error(code: CryptorRSA.ERR_ENCRYPTION_FAILED, reason: "Encryption failed. Unable to determine error.") - } - - throw Error(code: CryptorRSA.ERR_ENCRYPTION_FAILED, reason: "Encryption failed with error: \(error)") - } - - return EncryptedData(with: eData! as Data) + #else + + var response: Unmanaged? = nil + let eData = SecKeyCreateEncryptedData(key.reference, algorithm.alogrithmForEncryption, self.data as CFData, &response) + if response != nil { + + guard let error = response?.takeRetainedValue() else { + + throw Error(code: CryptorRSA.ERR_ENCRYPTION_FAILED, reason: "Encryption failed. Unable to determine error.") + } + + throw Error(code: CryptorRSA.ERR_ENCRYPTION_FAILED, reason: "Encryption failed with error: \(error)") + } + + return EncryptedData(with: eData! as Data) - #endif + #endif } /// @@ -271,7 +271,7 @@ public class CryptorRSA { throw Error(code: CryptorRSA.ERR_KEY_NOT_PUBLIC, reason: "Supplied key is not private") } - #if os(Linux) + #if os(Linux) switch algorithm { case .gcm: @@ -281,23 +281,23 @@ public class CryptorRSA { return try decryptedCBC(with: key) } - #else - - var response: Unmanaged? = nil - let pData = SecKeyCreateDecryptedData(key.reference, algorithm.alogrithmForEncryption, self.data as CFData, &response) - if response != nil { - - guard let error = response?.takeRetainedValue() else { - - throw Error(code: CryptorRSA.ERR_DECRYPTION_FAILED, reason: "Decryption failed. Unable to determine error.") - } - - throw Error(code: CryptorRSA.ERR_DECRYPTION_FAILED, reason: "Decryption failed with error: \(error)") - } - - return PlaintextData(with: pData! as Data) - - #endif + #else + + var response: Unmanaged? = nil + let pData = SecKeyCreateDecryptedData(key.reference, algorithm.alogrithmForEncryption, self.data as CFData, &response) + if response != nil { + + guard let error = response?.takeRetainedValue() else { + + throw Error(code: CryptorRSA.ERR_DECRYPTION_FAILED, reason: "Decryption failed. Unable to determine error.") + } + + throw Error(code: CryptorRSA.ERR_DECRYPTION_FAILED, reason: "Decryption failed with error: \(error)") + } + + return PlaintextData(with: pData! as Data) + + #endif } /// @@ -309,18 +309,18 @@ public class CryptorRSA { let rsaEncryptCtx = EVP_CIPHER_CTX_new_wrapper() EVP_CIPHER_CTX_init_wrapper(rsaEncryptCtx) - // get rsaKey - guard let rsaKey = EVP_PKEY_get1_RSA(.make(optional: key.reference)) else { - let source = "Couldn't create key reference from key data" - if let reason = CryptorRSA.getLastError(source: source) { - throw Error(code: ERR_ADD_KEY, reason: reason) - } - throw Error(code: ERR_ADD_KEY, reason: source + ": No OpenSSL error reported.") - } - defer { - RSA_free(rsaKey) - } - + // get rsaKey + guard let rsaKey = EVP_PKEY_get1_RSA(.make(optional: key.reference)) else { + let source = "Couldn't create key reference from key data" + if let reason = CryptorRSA.getLastError(source: source) { + throw Error(code: ERR_ADD_KEY, reason: reason) + } + throw Error(code: ERR_ADD_KEY, reason: source + ": No OpenSSL error reported.") + } + defer { + RSA_free(rsaKey) + } + // Set the additional authenticated data (aad) as the RSA key modulus and publicExponent in an ASN1 sequence. guard let aad = key.publicKeyBytes else { let source = "Encryption failed" @@ -743,7 +743,7 @@ public class CryptorRSA { throw Error(code: CryptorRSA.ERR_KEY_NOT_PRIVATE, reason: "Supplied key is not private") } - #if os(Linux) + #if os(Linux) let md_ctx = EVP_MD_CTX_new_wrapper() @@ -788,23 +788,23 @@ public class CryptorRSA { return SignedData(with: Data(bytes: sig, count: sig_len)) - #else - - var response: Unmanaged? = nil - let sData = SecKeyCreateSignature(key.reference, algorithm.algorithmForSignature, self.data as CFData, &response) - if response != nil { - - guard let error = response?.takeRetainedValue() else { - - throw Error(code: CryptorRSA.ERR_SIGNING_FAILED, reason: "Signing failed. Unable to determine error.") - } - - throw Error(code: CryptorRSA.ERR_SIGNING_FAILED, reason: "Signing failed with error: \(error)") - } - - return SignedData(with: sData! as Data) - - #endif + #else + + var response: Unmanaged? = nil + let sData = SecKeyCreateSignature(key.reference, algorithm.algorithmForSignature, self.data as CFData, &response) + if response != nil { + + guard let error = response?.takeRetainedValue() else { + + throw Error(code: CryptorRSA.ERR_SIGNING_FAILED, reason: "Signing failed. Unable to determine error.") + } + + throw Error(code: CryptorRSA.ERR_SIGNING_FAILED, reason: "Signing failed with error: \(error)") + } + + return SignedData(with: sData! as Data) + + #endif } /// @@ -836,7 +836,7 @@ public class CryptorRSA { throw Error(code: CryptorRSA.ERR_NOT_SIGNED_DATA, reason: "Supplied signature is not of signed data type") } - #if os(Linux) + #if os(Linux) let md_ctx = EVP_MD_CTX_new_wrapper() @@ -874,23 +874,23 @@ public class CryptorRSA { return (rc == 1) ? true : false - #else - - var response: Unmanaged? = nil - let result = SecKeyVerifySignature(key.reference, algorithm.algorithmForSignature, self.data as CFData, signature.data as CFData, &response) - if response != nil { - - guard let error = response?.takeRetainedValue() else { - - throw Error(code: CryptorRSA.ERR_VERIFICATION_FAILED, reason: "Signature verification failed. Unable to determine error.") - } - - throw Error(code: CryptorRSA.ERR_VERIFICATION_FAILED, reason: "Signature verification failed with error: \(error)") - } - - return result - - #endif + #else + + var response: Unmanaged? = nil + let result = SecKeyVerifySignature(key.reference, algorithm.algorithmForSignature, self.data as CFData, signature.data as CFData, &response) + if response != nil { + + guard let error = response?.takeRetainedValue() else { + + throw Error(code: CryptorRSA.ERR_VERIFICATION_FAILED, reason: "Signature verification failed. Unable to determine error.") + } + + throw Error(code: CryptorRSA.ERR_VERIFICATION_FAILED, reason: "Signature verification failed with error: \(error)") + } + + return result + + #endif } // MARK: --- Utility diff --git a/Sources/CryptorRSA/CryptorRSADigest.swift b/Sources/CryptorRSA/CryptorRSADigest.swift index a0a421b..802a2be 100644 --- a/Sources/CryptorRSA/CryptorRSADigest.swift +++ b/Sources/CryptorRSA/CryptorRSADigest.swift @@ -19,7 +19,7 @@ // #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) - import CommonCrypto + import CommonCrypto #elseif os(Linux) import OpenSSL public typealias CC_LONG = size_t @@ -63,7 +63,7 @@ extension Data { /// Digest Length public var length: CC_LONG { - #if os(Linux) + #if os(Linux) switch self { @@ -86,33 +86,33 @@ extension Data { return CC_LONG(SHA_DIGEST_LENGTH) } - #else + #else - switch self { - - case .sha1: - return CC_LONG(CC_SHA1_DIGEST_LENGTH) - - case .sha224: - return CC_LONG(CC_SHA224_DIGEST_LENGTH) - - case .sha256: - return CC_LONG(CC_SHA256_DIGEST_LENGTH) - - case .sha384: - return CC_LONG(CC_SHA384_DIGEST_LENGTH) - - case .sha512: - return CC_LONG(CC_SHA512_DIGEST_LENGTH) - - case .gcm: - return CC_LONG(CC_SHA1_DIGEST_LENGTH) - } + switch self { + + case .sha1: + return CC_LONG(CC_SHA1_DIGEST_LENGTH) + + case .sha224: + return CC_LONG(CC_SHA224_DIGEST_LENGTH) + + case .sha256: + return CC_LONG(CC_SHA256_DIGEST_LENGTH) + + case .sha384: + return CC_LONG(CC_SHA384_DIGEST_LENGTH) + + case .sha512: + return CC_LONG(CC_SHA512_DIGEST_LENGTH) + + case .gcm: + return CC_LONG(CC_SHA1_DIGEST_LENGTH) + } - #endif + #endif } - #if os(Linux) + #if os(Linux) // Hash, padding type public var algorithmForSignature: (OpaquePointer?, Int32) { @@ -167,63 +167,63 @@ extension Data { } #else - - @available(macOS 10.12, iOS 10.0, *) - public var algorithmForSignature: SecKeyAlgorithm { - - switch self { - - case .sha1: - return .rsaSignatureMessagePKCS1v15SHA1 - - case .sha224: - return .rsaSignatureMessagePKCS1v15SHA224 - - case .sha256: - return .rsaSignatureMessagePKCS1v15SHA256 - - case .sha384: - return .rsaSignatureMessagePKCS1v15SHA384 - - case .sha512: - return .rsaSignatureMessagePKCS1v15SHA512 + + @available(macOS 10.12, iOS 10.0, *) + public var algorithmForSignature: SecKeyAlgorithm { + + switch self { + + case .sha1: + return .rsaSignatureMessagePKCS1v15SHA1 + + case .sha224: + return .rsaSignatureMessagePKCS1v15SHA224 + + case .sha256: + return .rsaSignatureMessagePKCS1v15SHA256 + + case .sha384: + return .rsaSignatureMessagePKCS1v15SHA384 + + case .sha512: + return .rsaSignatureMessagePKCS1v15SHA512 case .gcm: return .rsaSignatureMessagePKCS1v15SHA1 - } - } - - @available(macOS 10.12, iOS 10.0, *) - public var alogrithmForEncryption: SecKeyAlgorithm { - - switch self { - - case .sha1: - return .rsaEncryptionOAEPSHA1AESGCM - - case .sha224: - return .rsaEncryptionOAEPSHA224AESGCM - - case .sha256: - return .rsaEncryptionOAEPSHA256AESGCM - - case .sha384: - return .rsaEncryptionOAEPSHA384AESGCM - - case .sha512: - return .rsaEncryptionOAEPSHA512AESGCM + } + } + + @available(macOS 10.12, iOS 10.0, *) + public var alogrithmForEncryption: SecKeyAlgorithm { + + switch self { + + case .sha1: + return .rsaEncryptionOAEPSHA1AESGCM + + case .sha224: + return .rsaEncryptionOAEPSHA224AESGCM + + case .sha256: + return .rsaEncryptionOAEPSHA256AESGCM + + case .sha384: + return .rsaEncryptionOAEPSHA384AESGCM + + case .sha512: + return .rsaEncryptionOAEPSHA512AESGCM case .gcm: return .rsaEncryptionOAEPSHA1AESGCM - - } - } - - #endif + + } + } + + #endif /// The platform/alogorithm dependent function to be used. /// (UnsafePointer!, Int, UnsafeMutablePointer!) -> UnsafeMutablePointer! - #if os(Linux) + #if os(Linux) public var engine: (_ data: UnsafePointer, _ len: CC_LONG, _ md: UnsafeMutablePointer) -> UnsafeMutablePointer? { @@ -250,33 +250,33 @@ extension Data { } } - #else - - public var engine: (_ data: UnsafeRawPointer, _ len: CC_LONG, _ md: UnsafeMutablePointer) -> UnsafeMutablePointer? { - - switch self { - - case .sha1: - return CC_SHA1 - - case .sha224: - return CC_SHA224 - - case .sha256: - return CC_SHA256 - - case .sha384: - return CC_SHA384 - - case .sha512: - return CC_SHA512 - + #else + + public var engine: (_ data: UnsafeRawPointer, _ len: CC_LONG, _ md: UnsafeMutablePointer) -> UnsafeMutablePointer? { + + switch self { + + case .sha1: + return CC_SHA1 + + case .sha224: + return CC_SHA224 + + case .sha256: + return CC_SHA256 + + case .sha384: + return CC_SHA384 + + case .sha512: + return CC_SHA512 + case .gcm: return CC_SHA1 - } - } - - #endif + } + } + + #endif } diff --git a/Sources/CryptorRSA/CryptorRSAKey.swift b/Sources/CryptorRSA/CryptorRSAKey.swift index 223622e..a4efa2f 100644 --- a/Sources/CryptorRSA/CryptorRSAKey.swift +++ b/Sources/CryptorRSA/CryptorRSAKey.swift @@ -20,7 +20,7 @@ // #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) - import CommonCrypto + import CommonCrypto #elseif os(Linux) import OpenSSL #endif @@ -34,15 +34,15 @@ extension CryptorRSA { // MARK: Type Aliases - #if os(Linux) + #if os(Linux) public typealias NativeKey = OpaquePointer? - #else - - public typealias NativeKey = SecKey - - #endif + #else + + public typealias NativeKey = SecKey + + #endif // MARK: Class Functions @@ -58,11 +58,11 @@ extension CryptorRSA { /// public class func createPublicKey(with data: Data) throws -> PublicKey { - #if os(Linux) + #if os(Linux) let data = CryptorRSA.convertDerToPem(from: data, type: .publicType) - #endif + #endif return try PublicKey(with: data) } @@ -112,12 +112,12 @@ extension CryptorRSA { throw Error(code: ERR_INIT_PK, reason: "Couldn't decode base64 string") } - #if os(Linux) + #if os(Linux) // OpenSSL uses the PEM version when importing key... data = CryptorRSA.convertDerToPem(from: data, type: .publicType) - #endif + #endif return try PublicKey(with: data) } @@ -132,21 +132,21 @@ extension CryptorRSA { /// public class func createPublicKey(withPEM pemString: String) throws -> PublicKey { - #if os(Linux) + #if os(Linux) // OpenSSL takes the full PEM format... let keyData = pemString.data(using: String.Encoding.utf8)! return try PublicKey(with: keyData) - #else - - // Get the Base64 representation of the PEM encoded string after stripping off the PEM markers - let base64String = try CryptorRSA.base64String(for: pemString) - - return try createPublicKey(withBase64: base64String) - - #endif + #else + + // Get the Base64 representation of the PEM encoded string after stripping off the PEM markers + let base64String = try CryptorRSA.base64String(for: pemString) + + return try createPublicKey(withBase64: base64String) + + #endif } /// @@ -194,15 +194,15 @@ extension CryptorRSA { let dataIn = try Data(contentsOf: fullPath) - #if os(Linux) + #if os(Linux) let data = CryptorRSA.convertDerToPem(from: dataIn, type: .publicType) - #else - - let data = dataIn - - #endif + #else + + let data = dataIn + + #endif return try PublicKey(with: data) } @@ -227,19 +227,19 @@ extension CryptorRSA { let fullPath = URL(fileURLWithPath: #file).appendingPathComponent( path.appending(certNameFull) ).standardized // Import the data from the file... - #if os(Linux) + #if os(Linux) // In OpenSSL, we can just get the data and don't have to worry about stripping off headers etc. let data = try Data(contentsOf: fullPath) - #else - - // Get the Base64 representation of the PEM encoded string after stripping off the PEM markers... - let tmp = try String(contentsOf: fullPath, encoding: .utf8) - let base64 = try CryptorRSA.base64String(for: tmp) - let data = Data(base64Encoded: base64)! - - #endif + #else + + // Get the Base64 representation of the PEM encoded string after stripping off the PEM markers... + let tmp = try String(contentsOf: fullPath, encoding: .utf8) + let base64 = try CryptorRSA.base64String(for: tmp) + let data = Data(base64Encoded: base64)! + + #endif return try CryptorRSA.createPublicKey(data: data) } @@ -283,15 +283,15 @@ extension CryptorRSA { let dataIn = try Data(contentsOf: URL(fileURLWithPath: path)) - #if os(Linux) + #if os(Linux) let data = CryptorRSA.convertDerToPem(from: dataIn, type: .publicType) - #else - - let data = dataIn - - #endif + #else + + let data = dataIn + + #endif return try PublicKey(with: data) } @@ -331,7 +331,7 @@ extension CryptorRSA { /// internal class func createPublicKey(data: Data) throws -> PublicKey { - #if os(Linux) + #if os(Linux) let certbio = BIO_new(BIO_s_mem()) defer { @@ -362,45 +362,45 @@ extension CryptorRSA { } // Extract the certificate's public key data. - let evp_key: OpaquePointer? = .init(X509_get_pubkey(cert)) + let evp_key: OpaquePointer? = .init(X509_get_pubkey(cert)) if evp_key == nil { throw Error(code: ERR_CREATE_CERT_FAILED, reason: "Error getting public key from certificate") } - return PublicKey(with: evp_key) + return PublicKey(with: evp_key) - #else - - // Create a DER-encoded X.509 certificate object from the DER data... - let certificateData = SecCertificateCreateWithData(nil, data as CFData) - guard let certData = certificateData else { - - throw Error(code: ERR_CREATE_CERT_FAILED, reason: "Unable to create certificate from certificate data.") - } - - #if os(macOS) - - // Now extract the public key from it... - var key: SecKey? = nil - let status: OSStatus = withUnsafeMutablePointer(to: &key) { ptr in - - // Retrieves the public key from a certificate... - SecCertificateCopyPublicKey(certData, UnsafeMutablePointer(ptr)) - } - if status != errSecSuccess || key == nil { - - throw Error(code: ERR_EXTRACT_PUBLIC_KEY_FAILED, reason: "Unable to extract public key from data.") - } - - #else - - let key = SecCertificateCopyPublicKey(certData) - - #endif - - return PublicKey(with: key!) - - #endif + #else + + // Create a DER-encoded X.509 certificate object from the DER data... + let certificateData = SecCertificateCreateWithData(nil, data as CFData) + guard let certData = certificateData else { + + throw Error(code: ERR_CREATE_CERT_FAILED, reason: "Unable to create certificate from certificate data.") + } + + #if os(macOS) + + // Now extract the public key from it... + var key: SecKey? = nil + let status: OSStatus = withUnsafeMutablePointer(to: &key) { ptr in + + // Retrieves the public key from a certificate... + SecCertificateCopyPublicKey(certData, UnsafeMutablePointer(ptr)) + } + if status != errSecSuccess || key == nil { + + throw Error(code: ERR_EXTRACT_PUBLIC_KEY_FAILED, reason: "Unable to extract public key from data.") + } + + #else + + let key = SecCertificateCopyPublicKey(certData) + + #endif + + return PublicKey(with: key!) + + #endif } // MARK: -- Private Key Creation @@ -446,21 +446,21 @@ extension CryptorRSA { /// public class func createPrivateKey(withPEM pemString: String) throws -> PrivateKey { - #if os(Linux) + #if os(Linux) // OpenSSL takes the full PEM format... let keyData = pemString.data(using: String.Encoding.utf8)! return try PrivateKey(with: keyData) - #else - - // SecKey needs the PEM format stripped of the header info and converted to base64... - let base64String = try CryptorRSA.base64String(for: pemString) - - return try CryptorRSA.createPrivateKey(withBase64: base64String) - - #endif + #else + + // SecKey needs the PEM format stripped of the header info and converted to base64... + let base64String = try CryptorRSA.base64String(for: pemString) + + return try CryptorRSA.createPrivateKey(withBase64: base64String) + + #endif } /// @@ -506,15 +506,15 @@ extension CryptorRSA { let dataIn = try Data(contentsOf: fullPath) - #if os(Linux) + #if os(Linux) let data = CryptorRSA.convertDerToPem(from: dataIn, type: .privateType) - #else - - let data = dataIn - - #endif + #else + + let data = dataIn + + #endif return try PrivateKey(with: data) } @@ -597,9 +597,9 @@ extension CryptorRSA { #if os(Linux) var publicKeyBytes: Data? - deinit { - EVP_PKEY_free(.make(optional: reference)) - } + deinit { + EVP_PKEY_free(.make(optional: reference)) + } #endif /// Represents the type of key data contained. @@ -662,24 +662,24 @@ extension CryptorRSA { self.reference = nativeKey } - #if os(Linux) && !swift(>=4.1) - - /// - /// Create a key using a native key. - /// - /// - Parameters: - /// - nativeKey: Pointer to RSA key structure. - /// - type: Type of key. - /// - /// - Returns: New `RSAKey` instance. - /// - internal init(with nativeKey: UnsafeMutablePointer, type: KeyType) { - - self.type = type - self.reference = .make(optional: nativeKey) - } - - #endif + #if os(Linux) && !swift(>=4.1) + + /// + /// Create a key using a native key. + /// + /// - Parameters: + /// - nativeKey: Pointer to RSA key structure. + /// - type: Type of key. + /// + /// - Returns: New `RSAKey` instance. + /// + internal init(with nativeKey: UnsafeMutablePointer, type: KeyType) { + + self.type = type + self.reference = .make(optional: nativeKey) + } + + #endif } // MARK: - diff --git a/Sources/CryptorRSA/CryptorRSAUtilities.swift b/Sources/CryptorRSA/CryptorRSAUtilities.swift index 77b438c..4d024d7 100644 --- a/Sources/CryptorRSA/CryptorRSAUtilities.swift +++ b/Sources/CryptorRSA/CryptorRSAUtilities.swift @@ -72,18 +72,18 @@ public extension CryptorRSA { BIO_ctrl(bio, BIO_CTRL_FLUSH, 0, nil) } - var evp_key = EVP_PKEY_new() + var evp_key: OpaquePointer? // Read in the key data and process depending on key type... if type == .publicType { - PEM_read_bio_PUBKEY(bio, &evp_key, nil, nil) + evp_key = .init(PEM_read_bio_PUBKEY(bio, nil, nil, nil)) } else { - PEM_read_bio_PrivateKey(bio, &evp_key, nil, nil) + evp_key = .init(PEM_read_bio_PrivateKey(bio, nil, nil, nil)) } - return .make(optional: evp_key) + return evp_key } /// @@ -146,38 +146,38 @@ public extension CryptorRSA { } #else - - /// - /// Create a key from key data. - /// - /// - Parameters: - /// - keyData: `Data` representation of the key. - /// - type: Type of key data. - /// - /// - Returns: `SecKey` representation of the key. - /// - static func createKey(from keyData: Data, type: CryptorRSA.RSAKey.KeyType) throws -> NativeKey { - - var keyData = keyData - - let keyClass = type == .publicType ? kSecAttrKeyClassPublic : kSecAttrKeyClassPrivate - - let sizeInBits = keyData.count * MemoryLayout.size - let keyDict: [CFString: Any] = [ - kSecAttrKeyType: kSecAttrKeyTypeRSA, - kSecAttrKeyClass: keyClass, - kSecAttrKeySizeInBits: NSNumber(value: sizeInBits) - ] - - guard let key = SecKeyCreateWithData(keyData as CFData, keyDict as CFDictionary, nil) else { - - throw Error(code: ERR_ADD_KEY, reason: "Couldn't create key reference from key data") - } - - return key - - } - + + /// + /// Create a key from key data. + /// + /// - Parameters: + /// - keyData: `Data` representation of the key. + /// - type: Type of key data. + /// + /// - Returns: `SecKey` representation of the key. + /// + static func createKey(from keyData: Data, type: CryptorRSA.RSAKey.KeyType) throws -> NativeKey { + + var keyData = keyData + + let keyClass = type == .publicType ? kSecAttrKeyClassPublic : kSecAttrKeyClassPrivate + + let sizeInBits = keyData.count * MemoryLayout.size + let keyDict: [CFString: Any] = [ + kSecAttrKeyType: kSecAttrKeyTypeRSA, + kSecAttrKeyClass: keyClass, + kSecAttrKeySizeInBits: NSNumber(value: sizeInBits) + ] + + guard let key = SecKeyCreateWithData(keyData as CFData, keyDict as CFDictionary, nil) else { + + throw Error(code: ERR_ADD_KEY, reason: "Couldn't create key reference from key data") + } + + return key + + } + #endif /// diff --git a/Tests/CryptorRSATests/CryptorRSATests.swift b/Tests/CryptorRSATests/CryptorRSATests.swift index a5b5f91..d6aeaf4 100644 --- a/Tests/CryptorRSATests/CryptorRSATests.swift +++ b/Tests/CryptorRSATests/CryptorRSATests.swift @@ -203,17 +203,17 @@ class CryptorRSATests: XCTestCase { func test_publicKeysFromComplexPEMFileWorksCorrectly() { -// guard let input = CryptorRSATests.pemKeyString(name: "multiple-keys-testcase") else { -// XCTFail() -// return -// } -// -// let keys = CryptorRSA.PublicKey.publicKeys(withPEM: input) -// XCTAssertEqual(keys.count, 9) -// -// for publicKey in keys { -// XCTAssertTrue(publicKey.type == .publicType) -// } + guard let input = CryptorRSATests.pemKeyString(name: "multiple-keys-testcase") else { + XCTFail() + return + } + + let keys = CryptorRSA.PublicKey.publicKeys(withPEM: input) + XCTAssertEqual(keys.count, 9) + + for publicKey in keys { + XCTAssertTrue(publicKey.type == .publicType) + } } func test_publicKeysFromEmptyPEMFileReturnsEmptyArray() { From fd6adcd800c3e3c17da205857978709f2e73793b Mon Sep 17 00:00:00 2001 From: andy Date: Tue, 26 Feb 2019 16:52:01 +0000 Subject: [PATCH 11/11] Remove remaining whitespace changes --- Sources/CryptorRSA/CryptorRSADigest.swift | 4 +- Sources/CryptorRSA/CryptorRSAKey.swift | 58 ++++++++++---------- Sources/CryptorRSA/CryptorRSAUtilities.swift | 13 +++-- Tests/CryptorRSATests/CryptorRSATests.swift | 6 +- 4 files changed, 41 insertions(+), 40 deletions(-) diff --git a/Sources/CryptorRSA/CryptorRSADigest.swift b/Sources/CryptorRSA/CryptorRSADigest.swift index 802a2be..8a1dd97 100644 --- a/Sources/CryptorRSA/CryptorRSADigest.swift +++ b/Sources/CryptorRSA/CryptorRSADigest.swift @@ -105,8 +105,8 @@ extension Data { case .sha512: return CC_LONG(CC_SHA512_DIGEST_LENGTH) - case .gcm: - return CC_LONG(CC_SHA1_DIGEST_LENGTH) + case .gcm: + return CC_LONG(CC_SHA1_DIGEST_LENGTH) } #endif diff --git a/Sources/CryptorRSA/CryptorRSAKey.swift b/Sources/CryptorRSA/CryptorRSAKey.swift index a4efa2f..e291d4e 100644 --- a/Sources/CryptorRSA/CryptorRSAKey.swift +++ b/Sources/CryptorRSA/CryptorRSAKey.swift @@ -39,9 +39,9 @@ extension CryptorRSA { public typealias NativeKey = OpaquePointer? #else - + public typealias NativeKey = SecKey - + #endif // MARK: Class Functions @@ -400,7 +400,7 @@ extension CryptorRSA { return PublicKey(with: key!) - #endif + #endif } // MARK: -- Private Key Creation @@ -515,7 +515,7 @@ extension CryptorRSA { let data = dataIn #endif - + return try PrivateKey(with: data) } @@ -558,15 +558,15 @@ extension CryptorRSA { let dataIn = try Data(contentsOf: URL(fileURLWithPath: path)) - #if os(Linux) + #if os(Linux) let data = CryptorRSA.convertDerToPem(from: dataIn, type: .privateType) - #else - - let data = dataIn - - #endif + #else + + let data = dataIn + + #endif return try PrivateKey(with: data) } @@ -668,10 +668,10 @@ extension CryptorRSA { /// Create a key using a native key. /// /// - Parameters: - /// - nativeKey: Pointer to RSA key structure. - /// - type: Type of key. + /// - nativeKey: Pointer to RSA key structure. + /// - type: Type of key. /// - /// - Returns: New `RSAKey` instance. + /// - Returns: New `RSAKey` instance. /// internal init(with nativeKey: UnsafeMutablePointer, type: KeyType) { @@ -791,22 +791,22 @@ extension CryptorRSA { super.init(with: nativeKey, type: .publicType) } - #if os(Linux) && !swift(>=4.1) - - /// - /// Create a key using a native key. - /// - /// - Parameters: - /// - nativeKey: Pointer to RSA key structure. - /// - /// - Returns: New `RSAKey` instance. - /// - public init(with nativeKey: UnsafeMutablePointer) { - - super.init(with: nativeKey, type: .publicType) - } - - #endif + #if os(Linux) && !swift(>=4.1) + + /// + /// Create a key using a native key. + /// + /// - Parameters: + /// - nativeKey: Pointer to RSA key structure. + /// + /// - Returns: New `RSAKey` instance. + /// + public init(with nativeKey: UnsafeMutablePointer) { + + super.init(with: nativeKey, type: .publicType) + } + + #endif } // MARK: - diff --git a/Sources/CryptorRSA/CryptorRSAUtilities.swift b/Sources/CryptorRSA/CryptorRSAUtilities.swift index 4d024d7..97fc7e7 100644 --- a/Sources/CryptorRSA/CryptorRSAUtilities.swift +++ b/Sources/CryptorRSA/CryptorRSAUtilities.swift @@ -20,7 +20,7 @@ // #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) - import CommonCrypto + import CommonCrypto #elseif os(Linux) import OpenSSL #endif @@ -49,6 +49,7 @@ public extension CryptorRSA { static func createKey(from keyData: Data, type: CryptorRSA.RSAKey.KeyType) throws -> NativeKey { let keyData = keyData + // Create a memory BIO... let bio = BIO_new(BIO_s_mem()) @@ -151,15 +152,15 @@ public extension CryptorRSA { /// Create a key from key data. /// /// - Parameters: - /// - keyData: `Data` representation of the key. - /// - type: Type of key data. + /// - keyData: `Data` representation of the key. + /// - type: Type of key data. /// - /// - Returns: `SecKey` representation of the key. + /// - Returns: `SecKey` representation of the key. /// static func createKey(from keyData: Data, type: CryptorRSA.RSAKey.KeyType) throws -> NativeKey { var keyData = keyData - + let keyClass = type == .publicType ? kSecAttrKeyClassPublic : kSecAttrKeyClassPrivate let sizeInBits = keyData.count * MemoryLayout.size @@ -173,7 +174,7 @@ public extension CryptorRSA { throw Error(code: ERR_ADD_KEY, reason: "Couldn't create key reference from key data") } - + return key } diff --git a/Tests/CryptorRSATests/CryptorRSATests.swift b/Tests/CryptorRSATests/CryptorRSATests.swift index d6aeaf4..c3d3aa4 100644 --- a/Tests/CryptorRSATests/CryptorRSATests.swift +++ b/Tests/CryptorRSATests/CryptorRSATests.swift @@ -99,7 +99,7 @@ class CryptorRSATests: XCTestCase { let data = try Data(contentsOf: filePath) let publicKey = try? CryptorRSA.createPublicKey(extractingFrom: data) XCTAssertNotNil(publicKey) - XCTAssertTrue(publicKey?.type == .publicType) + XCTAssertTrue(publicKey!.type == .publicType) } } @@ -113,7 +113,7 @@ class CryptorRSATests: XCTestCase { let data = try Data(contentsOf: filePath) let publicKey = try? CryptorRSA.createPublicKey(extractingFrom: data) XCTAssertNotNil(publicKey) - XCTAssertTrue(publicKey?.type == .publicType) + XCTAssertTrue(publicKey!.type == .publicType) } } @@ -207,7 +207,7 @@ class CryptorRSATests: XCTestCase { XCTFail() return } - + let keys = CryptorRSA.PublicKey.publicKeys(withPEM: input) XCTAssertEqual(keys.count, 9)