Эх сурвалжийг харах

Added CryptoSwift RSA and Apple Security SecKey interoperability tests

Brandon Toms 3 жил өмнө
parent
commit
da650df148

+ 174 - 0
Tests/CryptoSwiftTests/RSASecKeyTests.swift

@@ -0,0 +1,174 @@
+//
+//  CryptoSwift
+//
+//  Copyright (C) 2014-2021 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
+//  This software is provided 'as-is', without any express or implied warranty.
+//
+//  In no event will the authors be held liable for any damages arising from the use of this software.
+//
+//  Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+//  - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
+//  - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//  - This notice may not be removed or altered from any source or binary distribution.
+//
+
+#if canImport(Security)
+
+  import Security
+  import XCTest
+  @testable import CryptoSwift
+
+  final class RSASecKeyTests: XCTestCase {
+
+    // MARK: SecKey <-> RSA Interoperability
+
+    /// From RSA -> External Representation -> SecKey
+    func testRSAExternalRepresentationPrivate() throws {
+
+      /// Generate a CryptoSwift RSA Key
+      let rsaCryptoSwift = try RSA(keySize: 1024)
+
+      /// Get the key's rawExternalRepresentation
+      let rsaCryptoSwiftRawRep = try rsaCryptoSwift.privateKeyDER()
+
+      /// We should be able to instantiate an RSA SecKey from this data
+      let attributes: [String: Any] = [
+        kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
+        kSecAttrKeyClass as String: kSecAttrKeyClassPrivate,
+        kSecAttrKeySizeInBits as String: 1024,
+        kSecAttrIsPermanent as String: false
+      ]
+      var error: Unmanaged<CFError>?
+      guard let rsaSecKey = SecKeyCreateWithData(Data(rsaCryptoSwiftRawRep) as CFData, attributes as CFDictionary, &error) else {
+        XCTFail("Error constructing SecKey from raw key data: \(error.debugDescription)")
+        return
+      }
+
+      /// Get the SecKey's external representation
+      var externalRepError: Unmanaged<CFError>?
+      guard let rsaSecKeyRawRep = SecKeyCopyExternalRepresentation(rsaSecKey, &externalRepError) as? Data else {
+        XCTFail("Failed to copy external representation for RSA SecKey")
+        return
+      }
+
+      // Ensure both the CryptoSwift Ext Rep and the SecKey Ext Rep match
+      XCTAssertEqual(rsaSecKeyRawRep, Data(rsaCryptoSwiftRawRep))
+      XCTAssertEqual(rsaSecKeyRawRep, try rsaCryptoSwift.externalRepresentation())
+    }
+
+    /// From RSA -> External Representation -> SecKey
+    func testRSAExternalRepresentationPublic() throws {
+
+      /// Generate a CryptoSwift RSA Key
+      let rsaCryptoSwift = try RSA(keySize: 1024)
+
+      /// Get the key's rawExternalRepresentation
+      let rsaCryptoSwiftRawRep = try rsaCryptoSwift.publicKeyDER()
+
+      /// We should be able to instantiate an RSA SecKey from this data
+      let attributes: [String: Any] = [
+        kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
+        kSecAttrKeyClass as String: kSecAttrKeyClassPublic,
+        kSecAttrKeySizeInBits as String: 1024,
+        kSecAttrIsPermanent as String: false
+      ]
+      var error: Unmanaged<CFError>?
+      guard let rsaSecKey = SecKeyCreateWithData(Data(rsaCryptoSwiftRawRep) as CFData, attributes as CFDictionary, &error) else {
+        XCTFail("Error constructing SecKey from raw key data: \(error.debugDescription)")
+        return
+      }
+
+      /// Get the SecKey's external representation
+      var externalRepError: Unmanaged<CFError>?
+      guard let rsaSecKeyRawRep = SecKeyCopyExternalRepresentation(rsaSecKey, &externalRepError) as? Data else {
+        XCTFail("Failed to copy external representation for RSA SecKey")
+        return
+      }
+
+      // Ensure both the CryptoSwift Ext Rep and the SecKey Ext Rep match
+      XCTAssertEqual(rsaSecKeyRawRep, Data(rsaCryptoSwiftRawRep))
+      XCTAssertEqual(rsaSecKeyRawRep, try rsaCryptoSwift.publicKeyExternalRepresentation())
+    }
+
+    /// SecKey -> External Representation -> CryptoSwift RSA
+    func testSecKeyExternalRepresentationPrivate() throws {
+      /// Generate a SecKey RSA Key
+      let parameters: [CFString: Any] = [
+        kSecAttrKeyType: kSecAttrKeyTypeRSA,
+        kSecAttrKeySizeInBits: 1024
+      ]
+
+      var error: Unmanaged<CFError>?
+
+      // Generate the RSA SecKey
+      guard let rsaSecKey = SecKeyCreateRandomKey(parameters as CFDictionary, &error) else {
+        XCTFail("Key Generation Error: \(error.debugDescription)")
+        return
+      }
+
+      /// Lets grab the external representation
+      var externalRepError: Unmanaged<CFError>?
+      guard let rsaSecKeyRawRep = SecKeyCopyExternalRepresentation(rsaSecKey, &externalRepError) as? Data else {
+        XCTFail("Failed to copy external representation for RSA SecKey")
+        return
+      }
+
+      // Ensure we can import the private RSA key into CryptoSwift
+      let rsaCryptoSwift = try RSA(rawRepresentation: rsaSecKeyRawRep)
+
+      XCTAssertNotNil(rsaCryptoSwift.d)
+      XCTAssertEqual(rsaSecKeyRawRep, try rsaCryptoSwift.externalRepresentation())
+    }
+
+    /// SecKey -> External Representation -> CryptoSwift RSA
+    func testSecKeyExternalRepresentationPublic() throws {
+      /// Generate a SecKey RSA Key
+      let parameters: [CFString: Any] = [
+        kSecAttrKeyType: kSecAttrKeyTypeRSA,
+        kSecAttrKeySizeInBits: 1024
+      ]
+
+      var error: Unmanaged<CFError>?
+
+      // Generate the RSA SecKey
+      guard let rsaSecKey = SecKeyCreateRandomKey(parameters as CFDictionary, &error) else {
+        XCTFail("Key Generation Error: \(error.debugDescription)")
+        return
+      }
+
+      // Extract the public key from the private RSA SecKey
+      guard let rsaSecKeyPublic = SecKeyCopyPublicKey(rsaSecKey) else {
+        XCTFail("Public Key Extraction Error")
+        return
+      }
+
+      /// Lets grab the external representation of the public key
+      var externalRepError: Unmanaged<CFError>?
+      guard let rsaSecKeyRawRep = SecKeyCopyExternalRepresentation(rsaSecKeyPublic, &externalRepError) as? Data else {
+        XCTFail("Failed to copy external representation for RSA SecKey")
+        return
+      }
+
+      // Ensure we can import the private RSA key into CryptoSwift
+      let rsaCryptoSwift = try RSA(rawRepresentation: rsaSecKeyRawRep)
+
+      XCTAssertNil(rsaCryptoSwift.d)
+      XCTAssertEqual(rsaSecKeyRawRep, try rsaCryptoSwift.externalRepresentation())
+    }
+  }
+
+  extension RSASecKeyTests {
+    static func allTests() -> [(String, (RSASecKeyTests) -> () throws -> Void)] {
+      let tests = [
+        ("testRSAExternalRepresentationPrivate", testRSAExternalRepresentationPrivate),
+        ("testRSAExternalRepresentationPublic", testRSAExternalRepresentationPublic),
+        ("testSecKeyExternalRepresentationPrivate", testSecKeyExternalRepresentationPrivate),
+        ("testSecKeyExternalRepresentationPublic", testSecKeyExternalRepresentationPublic)
+      ]
+
+      return tests
+    }
+  }
+
+#endif