ecc

Search:
Group by:

A Nim wrapper around the micro-ecc C library, providing Elliptic Curve Cryptography (ECC) primitives including ECDSA signing/verification and ECDH shared secret generation.

Copyright (c) 2026 Christian Zietz <czietz@gmx.net>

Licensed under the MIT license.

Types

Curve = object
Represents a curve and must be instantiated by newCurve
CurveType = enum
  Curve_secp160r1, Curve_secp192r1, Curve_secp224r1, Curve_secp256r1,
  Curve_secp256k1
Supported curves
ECCError = object of CatchableError
Exception raised by this library
ECDHSharedSecret = seq[char]
Represents a ECDH shared secret
ECDSASignature = seq[char]
Represents a ECDSA signature
ECKeyPair = tuple[public: ECPublicKey, private: ECPrivateKey]
Represents a key pair
ECPrivateKey = object
Represents a private key
ECPublicKey = object
Represents a public key
rngFunction = proc (dest: ptr UncheckedArray[char]; size: cuint): cuint {.cdecl.}

Procs

proc `=destroy`(P: var ECPrivateKey) {....raises: [], tags: [RootEffect],
                                       forbids: [].}
proc ecDsaHashAndSign(P: ECPrivateKey; message: openArray[char];
                      hasher = Sha_256): ECDSASignature {....raises: [ECCError],
    tags: [], forbids: [].}
Hashes a message with the given hasher, then signs the hash with the given private key, returning the signature.
proc ecDsaHashAndVerify(P: ECPublicKey; message: openArray[char];
                        signature: ECDSASignature; hasher = Sha_256): bool {.
    ...raises: [ECCError], tags: [], forbids: [].}

Hashes a message with the given hasher, then verifies the hash and signature versus the given public key.

Returns true if the signature is valid.

proc ecDsaSign(P: ECPrivateKey; messageHash: openArray[char]): ECDSASignature {.
    ...raises: [ECCError], tags: [], forbids: [].}

Signs a message hash with the given private key, returning the signature.

Note: According to the standard, the hash is truncated if it is longer than the curve length.

proc ecDsaVerify(P: ECPublicKey; messageHash: openArray[char];
                 signature: ECDSASignature): bool {....raises: [ECCError],
    tags: [], forbids: [].}

Verifies a message hash and signature versus the given public key

Returns true if the signature is valid.

proc ecHashedSharedSecret(P: ECPublicKey; Q: ECPrivateKey;
                          nonce: openArray[char] = []; hasher = Sha_256): seq[
    char] {....raises: [ECCError], tags: [], forbids: [].}

Generates a shared secret with someone else's public key and a private key

Then hashes the secret and and optional nonce, which must be shared by both parties, with the given hasher. Returns the hash, which can be used, e.g., as session-specific secret.

Note: Is susceptible to a "Length Extension Attack" when an attacker can control the nonce. In that situation, use ecHMACSharedSecret instead.

proc ecHMACSharedSecret(P: ECPublicKey; Q: ECPrivateKey;
                        info: openArray[char] = []): ShaDigest_256 {.
    ...raises: [ECCError], tags: [], forbids: [].}

Generates a shared secret with someone else's public key and a private key

Then performs a HKDF (HMAC-based Extract-and-Expand Key Derivation Function) with the shared secret as key and the optional info, which must be shared by both parties. Returns the HMAC SHA-256, which can be used, e.g., as session-specific secret.

proc ecSharedSecret(P: ECPublicKey; Q: ECPrivateKey): ECDHSharedSecret {.
    ...raises: [ECCError], tags: [], forbids: [].}

Generates a shared secret with someone else's public key and a private key

It is recommended that you hash the result before using it for symmetric encryption

proc getCurve(P: ECPrivateKey): Curve {....raises: [], tags: [], forbids: [].}
Returns the Curve the key is on
proc getCurve(P: ECPublicKey): Curve {....raises: [], tags: [], forbids: [].}
Returns the Curve the key is on
proc getCurveSize(C: Curve): int {....raises: [], tags: [], forbids: [].}
Returns the curve order / 8 ("length" of the curve in bytes)
proc getCurveType(C: Curve): CurveType {....raises: [], tags: [], forbids: [].}
Returns the CurveType
proc getPrivateKeySize(C: Curve): int {....raises: [], tags: [], forbids: [].}
Returns the length in bytes of the private key
proc getPublicKey(P: ECPrivateKey): ECPublicKey {....raises: [ECCError], tags: [],
    forbids: [].}
Computes the public key for a given private key
proc getPublicKeySize(C: Curve; compressed = false): int {....raises: [], tags: [],
    forbids: [].}
Returns the length in bytes of the public key (uncompressed or compressed)
proc getSharedSecretSize(C: Curve): int {....raises: [], tags: [], forbids: [].}
Returns the length in bytes of a ECDH shared secret
proc getSignatureSize(C: Curve): int {....raises: [], tags: [], forbids: [].}
Returns the length in bytes of a ECDSA signature
proc hmacSha256(key: openArray[char]; message: openArray[char]): ShaDigest_256 {.
    ...raises: [], tags: [], forbids: [].}

HMAC SHA-256 (hash-based message authentication code)

Generates the HMAC SHA-256 with a given key and message.

proc loadPrivateKey(C: Curve; bytes: openArray[char]): ECPrivateKey {.
    ...raises: [ECCError], tags: [], forbids: [].}
Imports a private key
proc loadPublicKey(C: Curve; bytes: openArray[char]; compressed = false): ECPublicKey {.
    ...raises: [ECCError], tags: [], forbids: [].}

Imports a public key

When compressed is set, compressed SEC1 v2 format is expected. Otherwise guess the key format based on the input length:

  • Compressed SEC1 v2 format (as returned by toBytes)
  • Uncompressed raw format (as returned by toBytes)
  • Uncompressed SEC1 v2 format (as returned by toBytesSec1)

If the key is invalid (wrong length, not on the curve), an ECCError is raised. Thus, this function may be used with untrusted input.

proc makeKeyPair(C: Curve): ECKeyPair {....raises: [ECCError], tags: [],
                                        forbids: [].}
Generates a pair of public and private key
proc newCurve(T: CurveType): Curve {....raises: [], tags: [], forbids: [].}
Instantiates a curve of given CurveType
proc toBytes(P: ECPrivateKey): seq[char] {....raises: [], tags: [], forbids: [].}
Exports a private key for storage
proc toBytes(P: ECPublicKey; compressed = false): seq[char] {....raises: [],
    tags: [], forbids: [].}

Exports a public key for storage, optionally in compressed format

Compressed keys are represented in SEC1 v2 format, whereas uncompressed keys are just the point coordinates. (See toBytesSec1 for export in SEC1 v2 compliant uncompressed format.)

proc toBytesSec1(P: ECPublicKey): seq[char] {....raises: [], tags: [], forbids: [].}
Exports a public key for storage, in SEC1-v2-compliant uncompressed format
proc useCustomRNG(RNG_func: rngFunction) {....raises: [], tags: [], forbids: [].}

Use custom random number generator (RNG)

By default, micro-ecc uses the system's secure random generator. This is the recommended mode of operation. However, on systems where micro-ecc fails to find a secure random generator, you can provide your own RNG. This RNG must be cryptographically secure, otherwise keys and signatures will be weak!

The function signature of the RNG is:

proc (dest: ptr UncheckedArray[char], size: cuint): cuint {.cdecl.}

The RNG must fill in size chars into the array dest and return 1. It can also return 0 to signal that the random generation failed.

proc useWeakInternalRNG(seed: int64) {....deprecated: "this RNG is not cryptographically secure",
                                       raises: [], tags: [], forbids: [].}
Deprecated: this RNG is not cryptographically secure

Use Nim's internal random number generator (RNG)

This not cryptographically secure and should only be used for testing! In particular, keys and signatures generated while using this RNG are weak.

Note: By default, micro-ecc uses the system's secure random generator. This is the recommended mode of operation.

proc zeroSequence(s: string) {....raises: [], tags: [], forbids: [].}
Zeroes the contents of a string
proc zeroSequence[T](s: openArray[T])
Zeroes the contents of a sequence