Argon2, Temmuz 2015'te Parola Özetleme Yarışmasının galibi olarak seçilen anahtar türetme fonksiyonudur.12 Lüksemburg Üniversitesi'nden Alex Biryukov, Daniel Dinu ve Dmitry Khovratovich tarafından tasarlanmıştır.3 Argon2'nin referans uygulaması, CC0 lisansı (yani kamu malı) veya Apache License 2.0 altında yayınlanmış ve üç ilgili sürüm sağlamıştır:
Üç modun her biri, aşağıda verilen üç parametre ile tanımlama yapmaya izin verir.
Argon2d'ye uygulanabilecek genel bir kripto analizi olmamasına rağmen, Argon2i fonksiyonuna karşı yayınlanan iki saldırı vardır. İlk saldırı sadece Argon2i'nin eski sürümüne uygulanabilirken, ikincisi en son sürüme kadar uzatılmıştır (1.3)5
İlk saldırı, zaman cezası6 olmadan, istenen alanın çeyreği ile beşte biri arasında kullanılması ile, tek geçişli Argon2i fonksiyonunu hesaplamanın ve yine zaman cezası olmadan, sadece / < **/2.71 alanı kullanarak birçok geçişli Argon2i hesaplamanın mümkün olduğunu göstermektedir. Argon2 yazarlarına göre, bu saldırı vektörü 1.3 sürümünde düzeltilmiştir7.
İkinci saldırı, Argon2i'nin, seçilen tüm parametreler için, örneğin; **(alan maliyeti), (zaman maliyeti), ve =∗8 olan izlek sayısı, karmaşıklığı O(<sup>7/4</sup> log()) olan bir algoritma ile hesaplanabildiğini göstermektedir.
Argon2 yazarları, Argon2i üç veya daha fazla geçişle kullanılırsa bu saldırının etkili olmadığını iddia eder.9 Bununla birlikte, Joël Alwen ve Jeremiah Blocki saldırıyı iyileştirmiş ve saldırının başarısız olması için Argon2i 1.3'ün bellek üzerinde 10'dan fazla geçişe ihtiyaç duyduğunu göstermiştir.10
<span style="color:blue;">Function
</span> Argon2
<span style="color:blue;">
Inputs:
</span>
password (
P
): Bytes (0..2
<sup>32
</sup>-1)
<span style="color:green;">Password (or message) to be hashed
</span>
salt (
S
): Bytes (8..2
<sup>32
</sup>-1)
<span style="color:green;">Salt (16 bytes recommended for password hashing)
</span>
parallelism (
p
): Number (1..2
<sup>24
</sup>-1)
<span style="color:green;">Degree of parallelism (i.e. number of threads)
</span>
tagLength (
T
): Number (4..2
<sup>32
</sup>-1)
<span style="color:green;">Desired number of returned bytes
</span>
memorySizeKB (
m
): Number (8p..2
<sup>32
</sup>-1)
<span style="color:green;">Amount of memory (in [./https://en.wikipedia.org/wiki/Kibibyte `` kibibytes]) to use
</span>
iterations (
t
): Number (1..2
<sup>32
</sup>-1)
<span style="color:green;">Number of iterations to perform
</span>
version (
v
): Number (0x13)
<span style="color:green;">The current version is 0x13 (19 decimal)
</span>
key (
K
): Bytes (0..2
<sup>32
</sup>-1)
<span style="color:green;">Optional key (Errata: PDF says 0..32 bytes, RFC says 0..2
<sup>32
</sup> bytes)
</span>
associatedData (
X
): Bytes (0..2
<sup>32
</sup>-1)
<span style="color:green;">Optional arbitrary extra data
</span>
hashType (
y
): Number (0=Argon2d, 1=Argon2i, 2=Argon2id)
<span style="color:blue;">
Output:
</span>
tag: Bytes (tagLength)
<span style="color:green;">The resulting generated bytes, tagLength bytes long
</span>
<span style="color:green;">Generate`` ``initial`` ``64-byte`` ``block`` ``H
<sub>0
</sub>.
</span>
<span style="color:green;">
All the input parameters are concatenated and input as a source of additional entropy.
Errata: RFC says H
<sub>0
</sub> is 64-bits; PDF says H
<sub>0
</sub> is 64-bytes.
Errata: RFC says the Hash is H^, the PDF says it's ℋ (but doesn't document what ℋ is). It's actually Blake2b.
Variable length items are prepended with their length as 32-bit little-endian integers.
</span>
buffer ← parallelism ∥ tagLength ∥ memorySizeKB ∥ iterations ∥ version ∥ hashType
∥ Length(password) ∥ Password
∥ Length(salt) ∥ salt
∥ Length(key) ∥ key
∥ Length(associatedData) ∥ associatedData
H
<sub>0
</sub> ← Blake2b(buffer, 64)
<span style="color:green;">//default`` ``hash`` ``size`` ``of`` ``Blake2b`` ``is`` ``64-bytes
</span>
<span style="color:green;">Calculate number of 1 KB blocks by rounding down memorySizeKB to the nearest multiple of 4*parallelism [./https://en.wikipedia.org/wiki/Kibibyte `` kibibytes]
</span>
blockCount ← Floor(memorySizeKB, 4*parallelism)
<span style="color:green;">Allocate two-dimensional array of 1 KiB blocks (parallelism rows x columnCount columns)
</span>
columnCount ← blockCount / parallelism;
<span style="color:green;">//In the RFC, columnCount is referred to as
q
</span>
<span style="color:green;">Compute the first and second block (i.e. column zero and one ) of each lane (i.e. row)
</span>
for
i ← 0
to
parallelism-1
do
<span style="color:green;">for each row
</span>
B
<sub>i
</sub>[0] ← Hash(H
<sub>0
</sub> ∥ 0 ∥ i, 1024)
<span style="color:green;">//Generate`` ``a`` ``1024-byte`` ``digest
</span>
B
<sub>i
</sub>[1] ← Hash(H
<sub>0
</sub> ∥ 1 ∥ i, 1024)
<span style="color:green;">//Generate`` ``a`` ``1024-byte`` ``digest
</span>
<span style="color:green;">Compute remaining columns of each lane
</span>
for
i ← 0
to
parallelism-1
do
<span style="color:green;">//for each row
</span>
for
j ← 2
to
columnCount-1
do
<span style="color:green;">//for each subsequent column
</span>
<span style="color:green;">
//i' and j' indexes depend if it's Argon2i, Argon2d, or Argon2id (See section 3.4)
</span>
i′, j′ ← GetBlockIndexes(i, j)
<span style="color:green;">//the GetBlockIndexes function is not defined
</span>
B
<sub>i
</sub>[j] = G(B
<sub>i
</sub>[j-1], B
<sub>i′
</sub>[j′])
<span style="color:green;">//the G hash function is not defined
</span>
<span style="color:green;">Further passes when iterations > 1
</span>
for
nIteration ← 2
to
iterations
do
for
i ← 0
to
parallelism-1
do
<span style="color:green;">for each row
</span>
for
j ← 0
to
columnCount-1
do
<span style="color:green;">//for each subsequent column
</span>
<span style="color:green;">
//i' and j' indexes depend if it's Argon2i, Argon2d, or Argon2id (See section 3.4)
</span>
i′, j′ ← GetBlockIndexes(i, j)
if
j == 0
then
B
<sub>i
</sub>[0] = G(B
<sub>i
</sub>[columnCount-1], B
<sub>i′
</sub>[j′])
else
B
<sub>i
</sub>[j] = G(B
<sub>i
</sub>[j-1], B
<sub>i′
</sub>[j′])
<span style="color:green;">Compute final block
C
as the XOR of the last column of each row
</span>
C ← B
<sub>0
</sub>[columnCount-1]
for
i ← 1
to
parallelism-1
do
C ← C
xor
B
<sub>i
</sub>[columnCount-1]
<span style="color:green;">Compute output tag
</span>
return
Hash(C, tagLength)
Argon2, 2<sup>32</sup> byte uzunluğuna kadar özet üretebilen özet fonksiyonunu kullanır. Bu özet fonksiyonu dahili olarak Blake2 üzerine kuruludur.
<span style="color:blue;">Function
</span> Hash(message, digestSize)
<span style="color:blue;">
Inputs:
</span>
message: Bytes (0..2
<sup>32
</sup>-1)
<span style="color:green;">Message to be hashed
</span>
digestSize: Integer (1..2
<sup>32
</sup>)
<span style="color:green;">Desired number of bytes to be returned
</span>
<span style="color:blue;">
Output:
</span>
digest: Bytes (digestSize)
<span style="color:green;">The resulting generated bytes, digestSize bytes long
</span>
<span style="color:green;">Hash
is a variable-length hash function, built using Blake2b, capable of generating
digests up to 2
<sup>32
</sup> bytes.
</span>
<span style="color:green;">If the requested digestSize is 64-bytes or lower, then we use Blake2b directly
</span>
if
(digestSize <= 64)
then
return
Blake2b(digestSize ∥ message, digestSize)
<span style="color:green;">//concatenate 32-bit little endian digestSize with the message bytes
</span>
<span style="color:green;">For desired hashes over 64-bytes (e.g. 1024 bytes for Argon2 blocks),
we use Blake2b to generate twice the number of needed 64-byte blocks,
and then only use 32-bytes from each block
</span>
<span style="color:green;">Calculate the number of whole blocks (knowing we're only going to use 32-bytes from each)
</span>
r ← Ceil(digestSize/32)-1;
<span style="color:green;">Generate r whole blocks.
</span>
<span style="color:green;">
Initial block is generated from message
</span>
V
<sub>1
</sub> ← Blake2b(digestSize ∥ message, 64);
<span style="color:green;">
Subsequent blocks are generated from previous blocks
</span>
for
i ← 2
to
r
do
V
<sub>i
</sub> ← Blake2b(V
<sub>i-1
</sub>, 64)
<span style="color:green;">
Generate the final (possibly partial) block
</span>
partialBytesNeeded ← digestSize – 32*r;
V
<sub>r+1
</sub> ← Blake2b(V
<sub>r
</sub>, partialBytesNeeded)
<span style="color:green;">Concatenate the first 32-bytes of each block V
<sub>i
</sub>
(except the possibly partial last block, which we take the whole thing)
</span>
<span style="color:green;">
Let A
<sub>i
</sub> represent the lower 32-bytes of block V
<sub>i
</sub></span>
return
A
<sub>1
</sub> ∥ A
<sub>2
</sub> ∥ ... ∥ A
<sub>r
</sub> ∥ V
<sub>r+1
</sub>
Orijinal kaynak: argon2. Creative Commons Atıf-BenzerPaylaşım Lisansı ile paylaşılmıştır.
Ne Demek sitesindeki bilgiler kullanıcılar vasıtasıyla veya otomatik oluşturulmuştur. Buradaki bilgilerin doğru olduğu garanti edilmez. Düzeltilmesi gereken bilgi olduğunu düşünüyorsanız bizimle iletişime geçiniz. Her türlü görüş, destek ve önerileriniz için iletisim@nedemek.page