diff --git a/Package.swift b/Package.swift index 3f8e174..a7f7e41 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:5.3 +// swift-tools-version:5.5 // The swift-tools-version declares the minimum version of Swift required to build this package. import PackageDescription @@ -14,7 +14,7 @@ let package = Package( dependencies: [ // Dependencies declare other packages that this package depends on. .package(url: "https://github.com/leif-ibsen/ASN1", from: "2.0.0"), - .package(url: "https://github.com/leif-ibsen/BigInt", from: "1.2.6"), + .package(url: "https://github.com/leif-ibsen/BigInt", from: "1.2.11"), ], targets: [ // Targets are the basic building blocks of a package. A target can define a module or a test suite. diff --git a/README.md b/README.md index 479b435..cbe9e78 100755 --- a/README.md +++ b/README.md @@ -1,21 +1,39 @@ -

Description

- +

SwiftECC

+

Contents:

+ SwiftECC provides elliptic curve cryptography in Swift. This encompasses: SwiftECC requires Swift 5.0. It also requires that the Int and UInt types be 64 bit types. -

Usage

+

Usage

In your project Package.swift file add a dependency like
dependencies: [ - .package(url: "https://github.com/leif-ibsen/SwiftECC", from: "2.1.0"), + .package(url: "https://github.com/leif-ibsen/SwiftECC", from: "2.2.0"), ] -

Basics

+

Basics

The basic concept in SwiftECC is the Elliptic Curve Domain, represented by the Domain class. Please, refer section 3.1 in [SEC 1] that describes the domain concept in detail. @@ -26,7 +44,7 @@ and it is possible to create your own characteristic 2, and odd prime characteri You need a public key in order to encrypt a message or verify a signature, and you need a private key in order to decrypt a message or sign a message. Given a domain, you can generate public/private key pairs or you can load them from the PEM- or DER encoding of existing keys. -

Encryption and Decryption

+

Encryption and Decryption

Encryption and decryption is done using the ECIES algorithm based on AES block cipher. The algorithm uses one of AES-128, AES-192 or AES-256 ciphers, depending on your choice.
The following cipher block modes are supported: @@ -38,16 +56,16 @@ The following cipher block modes are supported:
  • CTR - Counter mode
  • OFB - Output Feedback mode
  • -The encryption and decryption speed for domain EC256k1 (the bitcoin domain) was measured on a MacBook Pro 2018, 2,2 GHz 6-Core Intel Core i7. +The encryption and decryption speed for domain EC256k1 (the bitcoin domain) was measured on an iMac 2021, Apple M1 chip. The results using AES-128 are shown in the table below - units are Megabytes per second. - - - - - - + + + + + +
    Block ModeEncryptDecrypt
    GCM26 MByte/Sec26 MByte/Sec
    ECB19 MByte/Sec19 MByte/Sec
    CBC14 MByte/Sec16 MByte/Sec
    CFB20 MByte/Sec20 MByte/Sec
    CTR21 MByte/Sec21 MByte/Sec
    OFB25 MByte/Sec26 MByte/Sec
    GCM53 MByte/Sec53 MByte/Sec
    ECB30 MByte/Sec30 MByte/Sec
    CBC24 MByte/Sec25 MByte/Sec
    CFB23 MByte/Sec23 MByte/Sec
    CTR30 MByte/Sec30 MByte/Sec
    OFB29 MByte/Sec29 MByte/Sec

    BlueECC Compatibility

    Data encrypted by SwiftECC in the EC256r1 domain with AES128/GCM, in the EC384r1 domain with AES256/GCM @@ -94,7 +112,7 @@ giving
    The quick brown fox jumps over the lazy dog! -

    Signing and Verifying

    +

    Signing and Verifying

    Signing data and verifying signatures is performed using the ECDSA algorithm. It is possible to generate deterministic signatures as specificed in [RFC-6979] by setting the deterministic parameter to true in the sign operation. @@ -109,6 +127,10 @@ The message digest used in the process is determined from the domain field size Signatures created by SwiftECC in the EC256r1, EC384r1 and EC521r1 domains can be verified by IBM's BlueECC product using curve prime256v1, secp384r1 and secp521r1, respectively. Likewise, signatures created by BlueECC with one of the curves prime256v1, secp384r1 and secp521r1 can be verified by SwiftECC using domains EC256r1, EC384r1 and EC521r1, respectively. +

    CryptoKit Compatibility

    +Signatures created by SwiftECC in the EC256r1, EC384r1 and EC521r1 domains can be verified by Swift CryptoKit +using curve P256, P384 and P521, respectively. Likewise, signatures created by Swift CryptoKit with one of the curves +P256, P384 and P521 can be verified by SwiftECC using domains EC256r1, EC384r1 and EC521r1, respectively.

    Example

    import SwiftECC @@ -155,7 +177,52 @@ giving (for example):
    Signature is good -

    Creating Domains

    +

    Secret Key Agreement

    +Given your own private key and another party's public key, you can generate a byte array that can be used as a symmetric encryption key. +The other party can generate the same byte array by using his own private key and your public key. +

    Example

    + + import SwiftECC + + do { + let domain = Domain.instance(curve: .EC256r1) + + // Party A's keys + let (pubA, privA) = domain.makeKeyPair() + + // Party B's keys + let (pubB, privB) = domain.makeKeyPair() + + let info: Bytes = [1, 2, 3] + let secretA = try privA.keyAgreement(pubKey: pubB, length: 16, md: .SHA2_256, sharedInfo: info) + let secretB = try privB.keyAgreement(pubKey: pubA, length: 16, md: .SHA2_256, sharedInfo: info) + print(secretA) + print(secretB) + } catch { + print("Exception: \(error)") + } + +giving (for example):
    + + [92, 161, 137, 44, 47, 30, 6, 26, 43, 183, 199, 130, 19, 254, 232, 106] + [92, 161, 137, 44, 47, 30, 6, 26, 43, 183, 199, 130, 19, 254, 232, 106] + +For the key agreement to work, the two parties must agree on which domain to use, which message digest to use +and which shared information (possibly none) to use. +

    CryptoKit Compatibility

    +SwiftECC key agreement is compatible with Swift CryptoKit key agreement +in that the EC256r1, EC384r1 and EC521r1 domains correspond to CryptoKit's P256, P384 and P521 curves, +and the SHA2_256, SHA2_384 and SHA2_512 message digests correspond to CryptoKit's SHA256, SHA384 and SHA512 message digests. + +To convert a CryptoKit public key - e.g. 'pubKey' - to the corresponding SwiftECC public key:
    + + let eccKey = try ECPublickey(pem: pubKey.pemRepresentation) + +To convert a SwiftECC public key - e.g. 'pubKey' - to the corresponding CryptoKit public key:
    + + let ckKey = try P256.KeyAgreement.PublicKey(pemRepresentation: pubKey.pem) + +

    Creating Domains

    You can create your own domains as illustrated by the two examples below.

    Example

    @@ -199,7 +266,7 @@ This is example 3.6 from [GUIDE]. It shows how to make your own characteristic 2 import SwiftECC import BigInt - // Reduction polynomial for x^4 + x + 1 + // Reduction polynomial for x^4 + x^1 + 1 let rp = RP(4, 1) // Create the domain let domain = try Domain.instance(name: "EC4", rp: rp, a: BInt(8), b: BInt(9), gx: BInt(1), gy: BInt(1), order: BInt(22), cofactor: 2) @@ -231,7 +298,7 @@ giving
    Integer: 22 Integer: 2 -

    Elliptic Curve Arithmetic

    +

    Elliptic Curve Arithmetic

    SwiftECC implements the common elliptic curve arithmetic operations: + + +
  • +
    + + + + keyAgreement(pubKey:length:md:sharedInfo:cofactor:) + +
    +
    +
    +
    +
    +
    +

    Constructs a shared secret key using Diffie-Hellman key agreement - please refer [SEC 1] section 3.3.1

    +
    +

    Throws

    + An exception if this and pubKey do not belong to the same domain or length is negative + +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func keyAgreement(pubKey: ECPublicKey, length: Int, md: MessageDigestAlgorithm, sharedInfo: Bytes, cofactor: Bool = false) throws -> Bytes
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + + + + + + + + + + + + + +
    + + pubKey + + +
    +

    The other party’s public key

    +
    +
    + + length + + +
    +

    The required length of the shared secret

    +
    +
    + + md + + +
    +

    The message digest algorithm to use

    +
    +
    + + sharedInfo + + +
    +

    Information shared with the other party

    +
    +
    + + cofactor + + +
    +

    Use cofactor version - false is default

    +
    +
    +
    +
    +

    Return Value

    +

    A byte array which is the shared secret key

    +
    +
    +
    +
  • - diff --git a/docs/Classes/ECPublicKey.html b/docs/Classes/ECPublicKey.html index 47586ad..704314f 100644 --- a/docs/Classes/ECPublicKey.html +++ b/docs/Classes/ECPublicKey.html @@ -18,17 +18,17 @@

    Docs (100% documented)

    -

    +

    -

    +
    @@ -67,6 +67,9 @@ + + + +
  • +
    + + + + MessageDigestAlgorithm + +
    +
    +
    +
    +
    +
    +

    Message digest algorithms

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public enum MessageDigestAlgorithm : CaseIterable
    + +
    +
    +
    +
    +
  • @@ -223,11 +254,10 @@

    Declaration

    - diff --git a/docs/Enums/AESCipher.html b/docs/Enums/AESCipher.html index 7b33ae6..cb2181b 100644 --- a/docs/Enums/AESCipher.html +++ b/docs/Enums/AESCipher.html @@ -18,17 +18,17 @@

    Docs (100% documented)

    -

    +

    -

    +
    @@ -67,6 +67,9 @@
  • + + + + +
  • +
    + + + + keyAgreementParameter + +
    +
    +
    +
    +
    +
    +

    Invalid key agreement parameter

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    case keyAgreementParameter
    + +
    +
    +
    +
    +
  • @@ -496,11 +526,10 @@

    Declaration

    - diff --git a/docs/Enums/MessageDigestAlgorithm.html b/docs/Enums/MessageDigestAlgorithm.html new file mode 100644 index 0000000..1172147 --- /dev/null +++ b/docs/Enums/MessageDigestAlgorithm.html @@ -0,0 +1,238 @@ + + + + MessageDigestAlgorithm Enumeration Reference + + + + + + + + + + + + + +
    +
    +

    Docs (100% documented)

    +
    +
    + +
    +
    +
    +
    +
    + +
    +
    + +
    +
    +
    +

    MessageDigestAlgorithm

    +
    +
    + +
    public enum MessageDigestAlgorithm : CaseIterable
    + +
    +
    +

    Message digest algorithms

    + +
    +
    +
    +
      +
    • +
      + + + + SHA2_224 + +
      +
      +
      +
      +
      +
      +

      SHA2 224

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case SHA2_224
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + SHA2_256 + +
      +
      +
      +
      +
      +
      +

      SHA2 256

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case SHA2_256
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + SHA2_384 + +
      +
      +
      +
      +
      +
      +

      SHA2 384

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case SHA2_384
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + SHA2_512 + +
      +
      +
      +
      +
      +
      +

      SHA2 512

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case SHA2_512
      + +
      +
      +
      +
      +
    • +
    +
    +
    +
    + +
    +
    + + diff --git a/docs/Structs.html b/docs/Structs.html index 2bf60d0..5cd952a 100644 --- a/docs/Structs.html +++ b/docs/Structs.html @@ -18,17 +18,17 @@

    Docs (100% documented)

    -

    +

    -

    +
    @@ -67,6 +67,9 @@
  • + +
  • - - - encode(_:) + + + encode(_:_:)
    @@ -272,7 +275,7 @@

    Return Value

    Declaration

    Swift

    -
    public static func encode(_ input: Bytes) -> String
    +
    public static func encode(_ input: Bytes, _ linesize: Int = 76) -> String
    @@ -292,6 +295,18 @@

    Parameters

    + + + + linesize + + + +
    +

    Number of characters per line - 76 is default

    +
    + + @@ -362,11 +377,10 @@

    Return Value

    - diff --git a/docs/Structs/Point.html b/docs/Structs/Point.html index 7dd601b..09809b4 100644 --- a/docs/Structs/Point.html +++ b/docs/Structs/Point.html @@ -18,17 +18,17 @@

    Docs (100% documented)

    -

    +

    -

    +
    @@ -67,6 +67,9 @@
  • + + + + + + +
  • +
    + + + + keyAgreement(pubKey:length:md:sharedInfo:cofactor:) + +
    +
    +
    +
    +
    +
    +

    Constructs a shared secret key using Diffie-Hellman key agreement - please refer [SEC 1] section 3.3.1

    +
    +

    Throws

    + An exception if this and pubKey do not belong to the same domain or length is negative + +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func keyAgreement(pubKey: ECPublicKey, length: Int, md: MessageDigestAlgorithm, sharedInfo: Bytes, cofactor: Bool = false) throws -> Bytes
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + + + + + + + + + + + + + +
    + + pubKey + + +
    +

    The other party’s public key

    +
    +
    + + length + + +
    +

    The required length of the shared secret

    +
    +
    + + md + + +
    +

    The message digest algorithm to use

    +
    +
    + + sharedInfo + + +
    +

    Information shared with the other party

    +
    +
    + + cofactor + + +
    +

    Use cofactor version - false is default

    +
    +
    +
    +
    +

    Return Value

    +

    A byte array which is the shared secret key

    +
    +
    +
    +
  • - diff --git a/docs/docsets/.docset/Contents/Resources/Documents/Classes/ECPublicKey.html b/docs/docsets/.docset/Contents/Resources/Documents/Classes/ECPublicKey.html index 47586ad..704314f 100644 --- a/docs/docsets/.docset/Contents/Resources/Documents/Classes/ECPublicKey.html +++ b/docs/docsets/.docset/Contents/Resources/Documents/Classes/ECPublicKey.html @@ -18,17 +18,17 @@

    Docs (100% documented)

    -

    +

    -

    +
    @@ -67,6 +67,9 @@ + + + +
  • +
    + + + + MessageDigestAlgorithm + +
    +
    +
    +
    +
    +
    +

    Message digest algorithms

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public enum MessageDigestAlgorithm : CaseIterable
    + +
    +
    +
    +
    +
  • @@ -223,11 +254,10 @@

    Declaration

    - diff --git a/docs/docsets/.docset/Contents/Resources/Documents/Enums/AESCipher.html b/docs/docsets/.docset/Contents/Resources/Documents/Enums/AESCipher.html index 7b33ae6..cb2181b 100644 --- a/docs/docsets/.docset/Contents/Resources/Documents/Enums/AESCipher.html +++ b/docs/docsets/.docset/Contents/Resources/Documents/Enums/AESCipher.html @@ -18,17 +18,17 @@

    Docs (100% documented)

    -

    +

    -

    +
    @@ -67,6 +67,9 @@
  • + + + + +
  • +
    + + + + keyAgreementParameter + +
    +
    +
    +
    +
    +
    +

    Invalid key agreement parameter

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    case keyAgreementParameter
    + +
    +
    +
    +
    +
  • @@ -496,11 +526,10 @@

    Declaration

    - diff --git a/docs/docsets/.docset/Contents/Resources/Documents/Enums/MessageDigestAlgorithm.html b/docs/docsets/.docset/Contents/Resources/Documents/Enums/MessageDigestAlgorithm.html new file mode 100644 index 0000000..1172147 --- /dev/null +++ b/docs/docsets/.docset/Contents/Resources/Documents/Enums/MessageDigestAlgorithm.html @@ -0,0 +1,238 @@ + + + + MessageDigestAlgorithm Enumeration Reference + + + + + + + + + + + + + +
    +
    +

    Docs (100% documented)

    +
    +
    + +
    +
    +
    +
    +
    + +
    +
    + +
    +
    +
    +

    MessageDigestAlgorithm

    +
    +
    + +
    public enum MessageDigestAlgorithm : CaseIterable
    + +
    +
    +

    Message digest algorithms

    + +
    +
    +
    +
      +
    • +
      + + + + SHA2_224 + +
      +
      +
      +
      +
      +
      +

      SHA2 224

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case SHA2_224
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + SHA2_256 + +
      +
      +
      +
      +
      +
      +

      SHA2 256

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case SHA2_256
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + SHA2_384 + +
      +
      +
      +
      +
      +
      +

      SHA2 384

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case SHA2_384
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + SHA2_512 + +
      +
      +
      +
      +
      +
      +

      SHA2 512

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case SHA2_512
      + +
      +
      +
      +
      +
    • +
    +
    +
    +
    + +
    +
    + + diff --git a/docs/docsets/.docset/Contents/Resources/Documents/Structs.html b/docs/docsets/.docset/Contents/Resources/Documents/Structs.html index 2bf60d0..5cd952a 100644 --- a/docs/docsets/.docset/Contents/Resources/Documents/Structs.html +++ b/docs/docsets/.docset/Contents/Resources/Documents/Structs.html @@ -18,17 +18,17 @@

    Docs (100% documented)

    -

    +

    -

    +
    @@ -67,6 +67,9 @@
  • + +
  • - - - encode(_:) + + + encode(_:_:)
    @@ -272,7 +275,7 @@

    Return Value

    Declaration

    Swift

    -
    public static func encode(_ input: Bytes) -> String
    +
    public static func encode(_ input: Bytes, _ linesize: Int = 76) -> String
    @@ -292,6 +295,18 @@

    Parameters

    + + + + linesize + + + +
    +

    Number of characters per line - 76 is default

    +
    + + @@ -362,11 +377,10 @@

    Return Value

    - diff --git a/docs/docsets/.docset/Contents/Resources/Documents/Structs/Point.html b/docs/docsets/.docset/Contents/Resources/Documents/Structs/Point.html index 7dd601b..09809b4 100644 --- a/docs/docsets/.docset/Contents/Resources/Documents/Structs/Point.html +++ b/docs/docsets/.docset/Contents/Resources/Documents/Structs/Point.html @@ -18,17 +18,17 @@

    Docs (100% documented)

    -

    +

    -

    +
    @@ -67,6 +67,9 @@
  • + + + + +