Skip to content

Commit

Permalink
Merge pull request #74 from outfoxx/feature/pkcs8-import-export
Browse files Browse the repository at this point in the history
Use CryptoKit to derive the EC public key during PKCS8 import
  • Loading branch information
kdubb committed Jun 26, 2023
2 parents a7c2a81 + f4e128f commit e98d70d
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 9 deletions.
3 changes: 2 additions & 1 deletion Sources/ShieldSecurity/AlgorithmIdentifier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public extension AlgorithmIdentifier {

enum Error: Swift.Error {
case unsupportedAlgorithm
@available(*, deprecated, message: "No longer used")
case unsupportedECKeySize
}

Expand Down Expand Up @@ -81,7 +82,7 @@ public extension AlgorithmIdentifier {
// P-521, secp521r1
curve = iso.org.certicom.curve.ansip521r1.oid
default:
throw Error.unsupportedECKeySize
throw Error.unsupportedAlgorithm
}

self.init(
Expand Down
23 changes: 18 additions & 5 deletions Sources/ShieldSecurity/SecKeyPair.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
//

import Algorithms
import CryptoKit
import Foundation
import PotentASN1
import Security
Expand Down Expand Up @@ -518,13 +519,25 @@ private extension SecKey {
importKeyData = privateKeyInfo.privateKey

case iso.memberBody.us.ansix962.keyType.ecPublicKey.oid:
keyType = .ec

let ecPrivateKey = try ASN1.Decoder.decode(ECPrivateKey.self, from: privateKeyInfo.privateKey)
guard let publicKey = ecPrivateKey.publicKey else {
throw SecKeyPair.Error.invalidEncodedPrivateKey
guard
let curveOID = privateKeyInfo.privateKeyAlgorithm.parameters?.objectIdentifierValue
else {
throw SecKey.Error.importFailed
}

keyType = .ec
importKeyData = publicKey.bytes + ecPrivateKey.privateKey
switch curveOID {
case iso.memberBody.us.ansix962.curves.prime.prime256v1.oid:
importKeyData = try P256.Signing.PrivateKey(rawRepresentation: ecPrivateKey.privateKey).x963Representation
case iso.org.certicom.curve.ansip384r1.oid:
importKeyData = try P384.Signing.PrivateKey(rawRepresentation: ecPrivateKey.privateKey).x963Representation
case iso.org.certicom.curve.ansip521r1.oid:
importKeyData = try P521.Signing.PrivateKey(rawRepresentation: ecPrivateKey.privateKey).x963Representation
default:
throw AlgorithmIdentifier.Error.unsupportedAlgorithm
}

default:
throw AlgorithmIdentifier.Error.unsupportedAlgorithm
Expand Down Expand Up @@ -594,7 +607,7 @@ private extension SecKey {
// P-521, secp521r1
return (iso.org.certicom.curve.ansip521r1.oid, 66)
default:
throw AlgorithmIdentifier.Error.unsupportedECKeySize
throw AlgorithmIdentifier.Error.unsupportedAlgorithm
}
}

Expand Down
41 changes: 38 additions & 3 deletions Tests/SecKeyPairTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -213,11 +213,46 @@ class SecKeyPairTests: XCTestCase {
XCTAssertThrowsError(try SecKeyPair.import(fromData: exportedKeyData, withPassword: "456"))
}

func testImportExportEC() throws {
func testImportExportEC192() throws {

let exportedKeyData = try ecKeyPair.export()
let ecKeyPair =
try SecKeyPair.Builder(type: .ec, keySize: 192)
.generate(label: "Test 192 EC Key")
defer { try? ecKeyPair.delete() }

XCTAssertThrowsError(try SecKeyPair.import(fromData: ecKeyPair.export())) { error in
XCTAssertTrue(error is AlgorithmIdentifier.Error)
}
}

func testImportExportEC256() throws {

let ecKeyPair =
try SecKeyPair.Builder(type: .ec, keySize: 256)
.generate(label: "Test 256 EC Key")
defer { try? ecKeyPair.delete() }

_ = try SecKeyPair.import(fromData: ecKeyPair.export())
}

func testImportExportEC384() throws {

let ecKeyPair =
try SecKeyPair.Builder(type: .ec, keySize: 384)
.generate(label: "Test 384 EC Key")
defer { try? ecKeyPair.delete() }

_ = try SecKeyPair.import(fromData: ecKeyPair.export())
}

func testImportExportEC521() throws {

let ecKeyPair =
try SecKeyPair.Builder(type: .ec, keySize: 521)
.generate(label: "Test 521 EC Key")
defer { try? ecKeyPair.delete() }

_ = try SecKeyPair.import(fromData: exportedKeyData)
_ = try SecKeyPair.import(fromData: ecKeyPair.export())
}

func testCodable() throws {
Expand Down

0 comments on commit e98d70d

Please sign in to comment.