From f82d425c56167a9a89bf211ab3eaf5ec1c298649 Mon Sep 17 00:00:00 2001 From: Guillaume Le Vaillant Date: Wed, 17 Apr 2024 13:33:28 +0200 Subject: Add Argon2id KDF (without parallelism) --- NEWS | 6 ++++++ README.org | 3 ++- ironclad.asd | 1 + src/kdf/argon2.lisp | 18 ++++++++++++++---- src/kdf/kdf.lisp | 7 +++++++ src/package.lisp | 2 +- testing/test-vectors/argon2id.lisp | 39 ++++++++++++++++++++++++++++++++++++++ 7 files changed, 70 insertions(+), 6 deletions(-) create mode 100644 testing/test-vectors/argon2id.lisp diff --git a/NEWS b/NEWS index d1e57ab..ca7ebb2 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,11 @@ -*- mode: outline -*- +* Changes since version 0.60 + +** new features + +Added the Argon2id key derivation function (without parallelism). + * Version 0.60, released 2024-02-29 ** new features diff --git a/README.org b/README.org index df0f2c3..b78371e 100644 --- a/README.org +++ b/README.org @@ -916,7 +916,7 @@ Returns ~t~ if /name/ would be in the list returned by :END: Ironclad comes with a few key derivation functions: - - Argon2 (only Argon2d and Argon2i without parallelism are implemented) + - Argon2 (only variants without parallelism are implemented) - Bcrypt - Bcrypt-pbkdf - PBKDF1 @@ -952,6 +952,7 @@ Returns a key derivation function instance. /kind/ denotes the key derivation function to use. They are: - argon2d - argon2i + - argon2id - bcrypt - bcrypt-pbkdf - pbkdf1 diff --git a/ironclad.asd b/ironclad.asd index c3dab83..c73014e 100644 --- a/ironclad.asd +++ b/ironclad.asd @@ -380,6 +380,7 @@ (:file "pkcs5") (:file "argon2d") (:file "argon2i") + (:file "argon2id") (:file "bcrypt") (:file "scrypt") (:file "hmac-kdf") diff --git a/src/kdf/argon2.lisp b/src/kdf/argon2.lisp index 0dee0e2..8dfbe2b 100644 --- a/src/kdf/argon2.lisp +++ b/src/kdf/argon2.lisp @@ -1,7 +1,7 @@ ;;;; -*- mode: lisp; indent-tabs-mode: nil -*- ;;;; argon2.lisp -- implementation of the Argon2 key derivation function -;;; Based on the Argon2i implementation present in the Monocypher +;;; Based on the Argon2 implementation present in the Monocypher ;;; crypto library (http://loup-vaillant.fr/projects/monocypher/) (in-package :crypto) @@ -27,6 +27,9 @@ (defclass argon2d (argon2) ()) +(defclass argon2id (argon2) + ()) + (defconstant +argon2-block-size+ 128) (deftype argon2-block () @@ -191,7 +194,9 @@ (aref b 2) (argon2-slice-number state) (aref b 3) (argon2-nb-blocks state) (aref b 4) (argon2-nb-iterations state) - (aref b 5) 1 + (aref b 5) (etypecase state + (argon2i 1) + (argon2id 2)) (aref b 6) (argon2-counter state)) (fill b 0 :start 7) (argon2-unary-g b) @@ -281,7 +286,7 @@ (when (or (< key-length 4) (< iteration-count 1) (< (length salt) 8)) (error 'unsupported-argon2-parameters)) (setf (argon2-nb-iterations kdf) iteration-count) - (let ((data-independent-p (typep kdf 'argon2i)) + (let ((data-independent-p (or (typep kdf 'argon2i) (typep kdf 'argon2id))) (work-area (argon2-work-area kdf)) (block-count (argon2-block-count kdf)) (additional-key (argon2-additional-key kdf)) @@ -298,7 +303,10 @@ (argon2-update-digester-32 digester block-count) (argon2-update-digester-32 digester iteration-count) (argon2-update-digester-32 digester #x13) - (argon2-update-digester-32 digester (if data-independent-p 1 0)) + (argon2-update-digester-32 digester (etypecase kdf + (argon2d 0) + (argon2i 1) + (argon2id 2))) (argon2-update-digester-32 digester (length passphrase)) (update-mac digester passphrase) (argon2-update-digester-32 digester (length salt)) @@ -330,6 +338,8 @@ (dotimes (pass-number iteration-count) (let ((first-pass (zerop pass-number))) (dotimes (segment 4) + (when (and (= segment 2) (typep kdf 'argon2id)) + (setf data-independent-p nil)) (if data-independent-p (argon2i-gidx-init kdf pass-number segment nb-blocks iteration-count) (argon2d-gidx-init kdf pass-number segment nb-blocks iteration-count)) diff --git a/src/kdf/kdf.lisp b/src/kdf/kdf.lisp index 97243ad..643039b 100644 --- a/src/kdf/kdf.lisp +++ b/src/kdf/kdf.lisp @@ -50,6 +50,13 @@ argon2" :block-count block-count :additional-key additional-key :additional-data additional-data)) + (argon2id + (when (< block-count 8) + (error 'unsupported-argon2-parameters)) + (make-instance 'argon2id + :block-count block-count + :additional-key additional-key + :additional-data additional-data)) (bcrypt (make-instance 'bcrypt)) (bcrypt-pbkdf diff --git a/src/package.lisp b/src/package.lisp index ce15543..68a4a16 100644 --- a/src/package.lisp +++ b/src/package.lisp @@ -54,7 +54,7 @@ ;; KDFs #:list-all-kdfs - #:pbkdf1 #:pbkdf2 #:hmac-kdf #:scrypt-kdf #:argon2i #:argon2d + #:pbkdf1 #:pbkdf2 #:hmac-kdf #:scrypt-kdf #:argon2i #:argon2d #:argon2id #:bcrypt #:bcrypt-pbkdf #:make-kdf #:derive-key diff --git a/testing/test-vectors/argon2id.lisp b/testing/test-vectors/argon2id.lisp new file mode 100644 index 0000000..4487955 --- /dev/null +++ b/testing/test-vectors/argon2id.lisp @@ -0,0 +1,39 @@ +;;;; -*- mode: lisp; indent-tabs-mode: nil -*- +(in-package :crypto-tests) + + +(rtest:deftest argon2id-1 + (run-kdf-test (crypto:make-kdf 'crypto:argon2id :block-count 12) + (crypto:ascii-string-to-byte-array "somepassword") + (crypto:ascii-string-to-byte-array "somesalt") + 3 + 32 + (ironclad:hex-string-to-byte-array "e77e03eafc1b9e867a1e7f38832e7d9fb73b04ef403ec2267f8e14e873448f0b")) + t) + +(rtest:deftest argon2id-2 + (run-kdf-test (crypto:make-kdf 'crypto:argon2id :block-count 32) + (crypto:ascii-string-to-byte-array "0123456789abcdefgh") + (crypto:ascii-string-to-byte-array "0123456789") + 3 + 32 + (ironclad:hex-string-to-byte-array "955d9f804edbd323ca241d2e53e43585c339535ca67d11a0768f60c7acd9e434")) + t) + +(rtest:deftest argon2id-3 + (run-kdf-test (crypto:make-kdf 'crypto:argon2id :block-count 64) + (crypto:ascii-string-to-byte-array "0000000000000000") + (crypto:ascii-string-to-byte-array "00000000") + 4 + 32 + (ironclad:hex-string-to-byte-array "ff40a8eabe934ba7831abf10fe86d368590470882c7af2a83aacd99d9877b0db")) + t) + +(rtest:deftest argon2id-4 + (run-kdf-test (crypto:make-kdf 'crypto:argon2id :block-count 128) + (crypto:ascii-string-to-byte-array "zzzzzzzzyyyyyyyyxxxxx") + (crypto:ascii-string-to-byte-array "wwwwwwwwvvvvv") + 3 + 111 + (ironclad:hex-string-to-byte-array "a2978bd1ef90d5f623ccfa74348e5f4ae72dca1af4fc1161b3a38ef6820f3600cdb70cc557c1f029960d725df5159b47af5163e174ce20a2fbb4e2b37ab5d66800f8467b23d848a8c8cb5347d8b93c56ae9525c5990c91153a9ce26ce06cc2d350d8db43cb89761bc43698a9f7e08c")) + t) -- cgit v1.2.3-70-g09d2