View Source pqclean NIF

Build Status Hex.pm

Post-Quantum Cryptography NIF based on PQClean for Erlang and Elixir.

See documentation for the pqclean_nif module for the full list of types and functions provided.

installation

Installation

Add pqclean to your project's dependencies in mix.exs

defp deps do
  [
    {:pqclean, "~> 0.0.3"}
  ]
end

Add pqclean to your project's dependencies in your Makefile for erlang.mk or the following to your rebar.config

{deps, [
    {pqclean, "0.0.3"}
]}.

examples

Examples

key-encapsulation-mechanism-kem-algorithm-example

Key Encapsulation Mechanism (KEM) Algorithm Example

{PK, SK} = pqclean_nif:kyber768_keypair(),
{CT, SS} = pqclean_nif:kyber768_encapsulate(PK),
     SS  = pqclean_nif:kyber768_decapsulate(CT, SK).

KEM with Encryption Example

% Alice and Bob want to exchange an encrypted messages.
% Alice wants to send Bob the message "a2b".
% Bob wants to send Alice the message "b2a".

% Helper functions (encrypt/decrypt with AES-256-GCM):
Encrypt = fun(K, N, PTxt) ->
    crypto:crypto_one_time_aead(aes_256_gcm, K, <<N:96>>, PTxt, <<>>, true)
end,
Decrypt = fun(K, N, CTxt, CTag) ->
    crypto:crypto_one_time_aead(aes_256_gcm, K, <<N:96>>, CTxt, <<>>, CTag, false)
end.

% Alice generates a new ephemeral keypair using Kyber-768:
{PKa, SKa} = pqclean_nif:kyber768_keypair().

% Alice sends `PKa' to Bob.

% Bob generates a new ephemeral keypair using Kyber-768:
{PKb, SKb} = pqclean_nif:kyber768_keypair(),
% Bob encapsulates a shared-secret `SSb2a' against Alice's `PKa' with
% an ephemeral KEM cipher-text `CTb2a' using Kyber-768:
{CTb2a, SSb2a} = pqclean_nif:kyber768_encapsulate(PKa),
% Bob encrypts plain-text `PKb' with shared-secret `SSb2a' and nonce `0'
% into cipher-text `CTxt_PKb' and cipher-tag `CTag_PKb':
{CTxt_PKb, CTag_PKb} = Encrypt(SSb2a, 0, PKb),
% Bob encrypts plain-text "b2a" with shared-secret `SSb2a' and nonce `1'
% into cipher-text `CTxt_PKb' and cipher-tag `CTag_PKb':
{CTxt_Mb, CTag_Mb} = Encrypt(SSb2a, 1, <<"b2a">>).

% Bob sends `CTb2a', `CTxt_PKb', `CTag_PKb', `CTxt_Mb', and `CTag_Mb' to Alice.

% Alice decapsulates Bob's `CTb2a' using secret-key `SKa' which
% results in shared-secret `SSb2a' using Kyber-768:
SSb2a = pqclean_nif:kyber768_decapsulate(CTb2a, SKa),
% Alice decrypts `PKb' with shared-secret `SSb2a':
PKb = Decrypt(SSb2a, 0, CTxt_PKb, CTag_PKb),
% Alice decrypts Bob's message "b2a" using shared-secret `SSb2a':
<<"b2a">> = Decrypt(SSb2a, 1, CTxt_Mb, CTag_Mb),
% Alice encapsulates a shared-secret `SSa2b' against Bob's `PKb' with
% an ephemeral KEM cipher-text `CTa2b' using Kyber-768:
{CTa2b, SSa2b} = pqclean_nif:kyber768_encapsulate(PKb),
% Alice encrypts plain-text "a2b" with shared-secret `SSa2b' and nonce `0'
% into cipher-text `CTxt_Ma' and cipher-tag `CTag_Ma':
{CTxt_Ma, CTag_Ma} = Encrypt(SSa2b, 0, <<"a2b">>).

% Alice sends `CTa2b', `CTxt_Ma', and `CTag_Ma' to Bob.

% Bob decapsulates Alice's `CTa2b' using secret-key `SKb' which
% results in shared-secret `SSa2b' using Kyber-768:
SSa2b = pqclean_nif:kyber768_decapsulate(CTa2b, SKb),
% Bob decrypts Alice's message "a2b" using shared-secret `SSa2b':
<<"a2b">> = Decrypt(SSa2b, 0, CTxt_Ma, CTag_Ma).

% Alice sends Bob a total of 2,291-bytes.
% Bob sends Alice a total of 2,307-bytes.

See PQNoise for more in-depth examples.

signature-algorithm-example

Signature Algorithm Example

{PK, SK} = pqclean_nif:falcon512_keypair(),
Msg = <<"message">>,
Sig = pqclean_nif:falcon512_sign(Msg, SK),
true = pqclean_nif:falcon512_verify(Sig, Msg, PK).

kem-algorithm-support

KEM Algorithm Support

KEM AlgorithmNIST LevelPublic KeySecret KeyCipher TextShared Secret
HQC-RMRS-12812,2492,2894,48164
HQC-RMRS-19234,5224,5629,02664
HQC-RMRS-25657,2457,28514,46964
Kyber51218001,63276832
Kyber512-90s18001,63276832
Kyber76831,1842,4001,08832
Kyber768-90s31,1842,4001,08832
Kyber102451,5683,1681,56832
Kyber1024-90s51,5683,1681,56832
Classic McEliece 3488641261,1206,45212832
Classic McEliece 348864f1261,1206,45212832
Classic McEliece 4608963524,16013,56818832
Classic McEliece 460896f3524,16013,56818832
Classic McEliece 668812851,044,99213,89224032
Classic McEliece 668812851,044,99213,89224032
Classic McEliece 696011951,047,31913,90822632
Classic McEliece 6960119f51,047,31913,90822632
Classic McEliece 819212851,357,82414,08024032
Classic McEliece 8192128f51,357,82414,08024032

WARNING: Algorithms marked with a dagger (†) require a large stack for key generation. See below for more information.

large-stack-support

Large Stack Support

When generating keys for "large stack" algorithms, an exception will be raised if the detected stack size is below 8MB:

1> try pqclean_nif:mceliece348864_keypair() catch error:{badarg, {_File, _Line}, Reason} -> Reason end.
"Key generation for Classic McEliece 348864 requires a large stack (>= 8MB): "
"please restart the BEAM with `erl +sssdcpu 1024` on 64-bit machines "
"(or `erl +sssdcpu 2048` on 32-bit machines); current setting is `erl +sssdcpu 41`"

Restarting the BEAM with erl +sssdcpu 1024 on 64-bit systems will allow key generation for these algorithms to be supported.

NOTE: If using an escript, rebar3, elixir, etc: it may be simpler to use the environment variable ERL_AFLAGS="+sssdcpu 1024" instead.

$ erl +sssdcpu 1024
1> {PK, SK} = pqclean_nif:mceliece348864_keypair().
{<<38,72,183,62,48,9,8,23,83,149,228,233,255,143,120,71,
   113,143,14,95,28,157,43,73,51,99,6,79,...>>,
 <<116,53,239,220,26,165,236,199,7,246,124,172,167,182,
   154,60,152,213,9,243,206,191,24,129,129,73,132,...>>}

signature-algorithm-support

Signature Algorithm Support

Signature AlgorithmNIST LevelPublic KeySecret KeySignatureSeed
Dilithium221,3122,5282,420
Dilithium2-AES21,3122,5282,420
Dilithium331,9524,0003,293
Dilithium3-AES31,9524,0003,293
Dilithium552,5924,8644,595
Dilithium5-AES52,5924,8644,595
Falcon-51218971,281666
Falcon-102451,7932,3051,280
SPHINCS+-haraka-128f-robust1326417,08848
SPHINCS+-haraka-128f-simple1326417,08848
SPHINCS+-haraka-128s-robust132647,85648
SPHINCS+-haraka-128s-simple132647,85648
SPHINCS+-haraka-192f-robust2489635,66472
SPHINCS+-haraka-192f-simple2489635,66472
SPHINCS+-haraka-192s-robust2489616,22472
SPHINCS+-haraka-192s-simple2489616,22472
SPHINCS+-haraka-256f-robust26412849,85696
SPHINCS+-haraka-256f-simple26412849,85696
SPHINCS+-haraka-256s-robust26412829,79296
SPHINCS+-haraka-256s-simple26412829,79296
SPHINCS+-sha2-128f-robust1326417,08848
SPHINCS+-sha2-128f-simple1326417,08848
SPHINCS+-sha2-128s-robust132647,85648
SPHINCS+-sha2-128s-simple132647,85648
SPHINCS+-sha2-192f-robust3489635,66472
SPHINCS+-sha2-192f-simple3489635,66472
SPHINCS+-sha2-192s-robust3489616,22472
SPHINCS+-sha2-192s-simple3489616,22472
SPHINCS+-sha2-256f-robust56412849,85696
SPHINCS+-sha2-256f-simple56412849,85696
SPHINCS+-sha2-256s-robust56412829,79296
SPHINCS+-sha2-256s-simple56412829,79296
SPHINCS+-shake-128f-robust1326417,08848
SPHINCS+-shake-128f-simple1326417,08848
SPHINCS+-shake-128s-robust132647,85648
SPHINCS+-shake-128s-simple132647,85648
SPHINCS+-shake-192f-robust3489635,66472
SPHINCS+-shake-192f-simple3489635,66472
SPHINCS+-shake-192s-robust3489616,22472
SPHINCS+-shake-192s-simple3489616,22472
SPHINCS+-shake-256f-robust56412849,85696
SPHINCS+-shake-256f-simple56412849,85696
SPHINCS+-shake-256s-robust56412829,79296
SPHINCS+-shake-256s-simple56412829,79296