Skip to content

Commit

Permalink
fix: Replace ECAlgorithm with EllipticCurve (#5)
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrew-Lees11 authored and djones6 committed Mar 5, 2019
1 parent 4cc3eea commit 6b7bc9e
Show file tree
Hide file tree
Showing 9 changed files with 175 additions and 150 deletions.
116 changes: 0 additions & 116 deletions Sources/CryptorECC/ECAlgorithm.swift

This file was deleted.

6 changes: 3 additions & 3 deletions Sources/CryptorECC/ECDecryptable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ extension Data {
EVP_CIPHER_CTX_init_wrapper(rsaDecryptCtx)

let tagLength = 16
let encKeyLength = key.algorithm.keySize
let encKeyLength = key.curve.keySize
let encryptedDataLength = Int(self.count) - encKeyLength - tagLength
// Extract encryptedAESKey, encryptedData, GCM tag from data
let encryptedKey = self.subdata(in: 0..<encKeyLength)
Expand Down Expand Up @@ -87,7 +87,7 @@ extension Data {
let symKeyData = Data(bytes: symKey, count: skey_len)
let counterData = Data(bytes: [0x00, 0x00, 0x00, 0x01])
let preHashKey = symKeyData + counterData + encryptedKey
let hashedKey = key.algorithm.digest(data: preHashKey)
let hashedKey = key.curve.digest(data: preHashKey)
let aesKey = [UInt8](hashedKey.subdata(in: 0 ..< 16))
let iv = [UInt8](hashedKey.subdata(in: 16 ..< 32))

Expand Down Expand Up @@ -131,7 +131,7 @@ extension Data {
#else
var error: Unmanaged<CFError>? = nil
guard let eData = SecKeyCreateDecryptedData(key.nativeKey,
key.algorithm.curve,
key.curve.encryptionAlgorithm,
self as CFData,
&error)
else {
Expand Down
14 changes: 7 additions & 7 deletions Sources/CryptorECC/ECEncryptable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ extension Data: ECEncryptable {
public func encrypt(with key: ECPublicKey) throws -> Data {
#if os(Linux)
// Compute symmetric key
let ec_key = EC_KEY_new_by_curve_name(key.algorithm.curve)
let ec_key = EC_KEY_new_by_curve_name(key.curve.nativeCurve)
defer {
EC_KEY_free(ec_key)
}
Expand All @@ -72,7 +72,7 @@ extension Data: ECEncryptable {
let pub = EC_KEY_get0_public_key(ec_key)
let pub_bn = BN_new()
EC_POINT_point2bn(ec_group, pub, POINT_CONVERSION_UNCOMPRESSED, pub_bn, pub_bn_ctx)
let pubk = UnsafeMutablePointer<UInt8>.allocate(capacity: key.algorithm.keySize)
let pubk = UnsafeMutablePointer<UInt8>.allocate(capacity: key.curve.keySize)
BN_bn2bin(pub_bn, pubk)
defer {
BN_CTX_end(pub_bn_ctx)
Expand All @@ -82,17 +82,17 @@ extension Data: ECEncryptable {
pubk.deallocate()
symKey.deallocate()
#else
pubk.deallocate(capacity: key.algorithm.keySize)
pubk.deallocate(capacity: key.curve.keySize)
symKey.deallocate(capacity: symKey_len)
#endif
}

// get aes key and iv using ANSI x9.63 Key Derivation Function
let symKeyData = Data(bytes: symKey, count: symKey_len)
let counterData = Data(bytes: [0x00, 0x00, 0x00, 0x01])
let sharedInfo = Data(bytes: pubk, count: key.algorithm.keySize)
let sharedInfo = Data(bytes: pubk, count: key.curve.keySize)
let preHashKey = symKeyData + counterData + sharedInfo
let hashedKey = key.algorithm.digest(data: preHashKey)
let hashedKey = key.curve.digest(data: preHashKey)
let aesKey = [UInt8](hashedKey.subdata(in: 0 ..< (hashedKey.count - 16)))
let iv = [UInt8](hashedKey.subdata(in: (hashedKey.count - 16) ..< hashedKey.count))

Expand Down Expand Up @@ -158,14 +158,14 @@ extension Data: ECEncryptable {
}

// Construct the envelope by combining the encrypted AES key, the encrypted date and the GCM tag.
let ekFinal = Data(bytes: pubk, count: key.algorithm.keySize)
let ekFinal = Data(bytes: pubk, count: key.curve.keySize)
let cipher = Data(bytes: encrypted, count: Int(encLength))
let tagFinal = Data(bytes: tag, count: 16)
return ekFinal + cipher + tagFinal
#else
var error: Unmanaged<CFError>? = nil
guard let eData = SecKeyCreateEncryptedData(key.nativeKey,
key.algorithm.curve,
key.curve.encryptionAlgorithm,
self as CFData,
&error)
else {
Expand Down
29 changes: 16 additions & 13 deletions Sources/CryptorECC/ECPrivateKey.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,19 @@ import OpenSSL
*/
@available(OSX 10.13, *)
public class ECPrivateKey {
/// The Elliptic curve this key was generated from.
/// A String description of the curve this key was generated from.
public let curveId: String

/// The `EllipticCurve` this key was generated from.
public let curve: EllipticCurve

#if os(Linux)
typealias NativeKey = OpaquePointer?
deinit { EC_KEY_free(.make(optional: self.nativeKey)) }
#else
typealias NativeKey = SecKey
#endif
let nativeKey: NativeKey
let algorithm: ECAlgorithm
let pubKeyBytes: Data


Expand Down Expand Up @@ -119,8 +122,7 @@ public class ECPrivateKey {
else {
throw ECError.failedASN1Decoding
}
self.algorithm = try ECAlgorithm.objectToHashAlg(ObjectIdentifier: privateKeyID)
self.curveId = self.algorithm.id.rawValue
self.curve = try EllipticCurve.objectToCurve(ObjectIdentifier: privateKeyID)
guard case let ASN1.ASN1Element.bytes(data: privateOctest) = es[2] else {
throw ECError.failedASN1Decoding
}
Expand All @@ -147,8 +149,9 @@ public class ECPrivateKey {
let trimmedPubBytes = publicKeyData.drop(while: { $0 == 0x00})
self.nativeKey = try ECPrivateKey.bytesToNativeKey(privateKeyData: privateKeyData,
publicKeyData: trimmedPubBytes,
algorithm: algorithm)
curve: curve)
self.pubKeyBytes = trimmedPubBytes
self.curveId = curve.description
}

/// Initialize an ECPrivateKey from a SEC1 `.der` file data.
Expand All @@ -167,8 +170,7 @@ public class ECPrivateKey {
else {
throw ECError.failedASN1Decoding
}
self.algorithm = try ECAlgorithm.objectToHashAlg(ObjectIdentifier: objectId)
self.curveId = self.algorithm.id.rawValue
self.curve = try EllipticCurve.objectToCurve(ObjectIdentifier: objectId)
guard case let ASN1.ASN1Element.constructed(tag: _, elem: publicElement) = seq[3],
case let ASN1.ASN1Element.bytes(data: publicKeyData) = publicElement
else {
Expand All @@ -177,8 +179,9 @@ public class ECPrivateKey {
let trimmedPubBytes = publicKeyData.drop(while: { $0 == 0x00})
self.nativeKey = try ECPrivateKey.bytesToNativeKey(privateKeyData: privateKeyData,
publicKeyData: trimmedPubBytes,
algorithm: algorithm)
curve: curve)
self.pubKeyBytes = trimmedPubBytes
self.curveId = curve.description
}

/// Initialize the `ECPublicKey`for this private key by extracting the public key bytes.
Expand All @@ -192,17 +195,17 @@ public class ECPrivateKey {
// OBJECT IDENTIFIER
// OBJECT IDENTIFIER
// BIT STRING (This is the `pubKeyBytes` added afterwards)
if self.algorithm.id == .prime256v1 {
if self.curve == .prime256v1 {
keyHeader = Data(bytes: [0x30, 0x59,
0x30, 0x13,
0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01,
0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42])
} else if self.algorithm.id == .secp384r1 {
} else if self.curve == .secp384r1 {
keyHeader = Data(bytes: [0x30, 0x76,
0x30, 0x10,
0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01,
0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22, 0x03, 0x62])
} else if self.algorithm.id == .secp521r1 {
} else if self.curve == .secp521r1 {
keyHeader = Data(bytes: [0x30, 0x81, 0x9B,
0x30, 0x10,
0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01,
Expand All @@ -219,7 +222,7 @@ public class ECPrivateKey {
}


private static func bytesToNativeKey(privateKeyData: Data, publicKeyData: Data, algorithm: ECAlgorithm) throws -> NativeKey {
private static func bytesToNativeKey(privateKeyData: Data, publicKeyData: Data, curve: EllipticCurve) throws -> NativeKey {
#if os(Linux)
let bigNum = BN_new()
defer {
Expand All @@ -228,7 +231,7 @@ public class ECPrivateKey {
privateKeyData.withUnsafeBytes({ (privateKeyBytes: UnsafePointer<UInt8>) -> Void in
BN_bin2bn(privateKeyBytes, Int32(privateKeyData.count), bigNum)
})
let ecKey = EC_KEY_new_by_curve_name(algorithm.curve)
let ecKey = EC_KEY_new_by_curve_name(curve.nativeCurve)
guard EC_KEY_set_private_key(ecKey, bigNum) == 1 else {
EC_KEY_free(ecKey)
throw ECError.failedNativeKeyCreation
Expand Down
12 changes: 7 additions & 5 deletions Sources/CryptorECC/ECPublicKey.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,11 @@ import OpenSSL
*/
@available(OSX 10.13, *)
public class ECPublicKey {
/// The Elliptic curve this key was generated from.
/// A String description of the curve this key was generated from.
public let curveId: String

/// The `EllipticCurve` this key was generated from.
public let curve: EllipticCurve
#if os(Linux)
typealias NativeKey = OpaquePointer?
let pubKeyBytes: Data
Expand All @@ -57,7 +60,6 @@ public class ECPublicKey {
typealias NativeKey = SecKey
#endif
let nativeKey: NativeKey
let algorithm: ECAlgorithm

/// The public key represented as a PEM String.
public let pemString: String
Expand Down Expand Up @@ -112,8 +114,8 @@ public class ECPublicKey {
else {
throw ECError.failedASN1Decoding
}
self.algorithm = try ECAlgorithm.objectToHashAlg(ObjectIdentifier: privateKeyID)
self.curveId = self.algorithm.id.rawValue
self.curve = try EllipticCurve.objectToCurve(ObjectIdentifier: privateKeyID)
self.curveId = curve.description
let keyData = publicKeyData.drop(while: { $0 == 0x00})
#if os(Linux)
self.pubKeyBytes = keyData
Expand All @@ -124,7 +126,7 @@ public class ECPublicKey {
publicKeyData.withUnsafeBytes({ (pubKeyBytes: UnsafePointer<UInt8>) -> Void in
BN_bin2bn(pubKeyBytes, Int32(publicKeyData.count), bigNum)
})
let ecKey = EC_KEY_new_by_curve_name(algorithm.curve)
let ecKey = EC_KEY_new_by_curve_name(curve.nativeCurve)
let ecGroup = EC_KEY_get0_group(ecKey)
let ecPoint = EC_POINT_new(ecGroup)
defer {
Expand Down
6 changes: 3 additions & 3 deletions Sources/CryptorECC/ECSignable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ extension Data: ECSignable {
throw ECError.failedNativeKeyCreation
}

guard EVP_DigestSignInit(md_ctx, nil, .make(optional: key.algorithm.signingAlgorithm), nil, evp_key) == 1 else {
guard EVP_DigestSignInit(md_ctx, nil, .make(optional: key.curve.signingAlgorithm), nil, evp_key) == 1 else {
throw ECError.failedEvpInit
}

Expand All @@ -84,13 +84,13 @@ extension Data: ECSignable {
}
return try ECSignature(asn1: Data(bytes: sig, count: sig_len))
#else
let hash = key.algorithm.digest(data: self)
let hash = key.curve.digest(data: self)

// Memory storage for error from SecKeyCreateSignature
var error: Unmanaged<CFError>? = nil
// cfSignature is CFData that is ANS1 encoded as a sequence of two UInts (r and s)
guard let cfSignature = SecKeyCreateSignature(key.nativeKey,
key.algorithm.signingAlgorithm,
key.curve.signingAlgorithm,
hash as CFData,
&error)
else {
Expand Down
6 changes: 3 additions & 3 deletions Sources/CryptorECC/ECSignature.swift
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public struct ECSignature {
return false
}

EVP_DigestVerifyInit(md_ctx, nil, .make(optional: ecPublicKey.algorithm.signingAlgorithm), nil, evp_key)
EVP_DigestVerifyInit(md_ctx, nil, .make(optional: ecPublicKey.curve.signingAlgorithm), nil, evp_key)
guard plaintext.withUnsafeBytes({ (message: UnsafePointer<UInt8>) -> Int32 in
return EVP_DigestUpdate(md_ctx, message, plaintext.count)
}) == 1 else {
Expand All @@ -107,12 +107,12 @@ public struct ECSignature {

return rc == 1
#else
let hash = ecPublicKey.algorithm.digest(data: plaintext)
let hash = ecPublicKey.curve.digest(data: plaintext)

// Memory storage for error from SecKeyVerifySignature
var error: Unmanaged<CFError>? = nil
return SecKeyVerifySignature(ecPublicKey.nativeKey,
ecPublicKey.algorithm.signingAlgorithm,
ecPublicKey.curve.signingAlgorithm,
hash as CFData,
self.asn1 as CFData,
&error)
Expand Down
Loading

0 comments on commit 6b7bc9e

Please sign in to comment.