Skip to content

Commit

Permalink
add comments describing the steps of the RFC algorithm
Browse files Browse the repository at this point in the history
  • Loading branch information
xemwebe committed Jul 17, 2023
1 parent 282baa5 commit 7537728
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 11 deletions.
51 changes: 44 additions & 7 deletions pkcs12/src/kdf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,44 +49,80 @@ where
let mut pass_utf16 = str_to_unicode(pass);
let output_size = <D as OutputSizeUser>::output_size();
let block_size = D::block_size();

// In the following, the numbered comments relate directly to the algorithm
// described in RFC 7292, Appendix B.2. Actual variable names may differ.
// Comments of the RFC are in enclosed in []
//
// 1. Construct a string, D (the "diversifier"), by concatenating v/8
// copies of ID, where v is the block size in bits.
let id_block = match id {
Pkcs12KeyType::EncryptionKey => vec![1u8; block_size],
Pkcs12KeyType::Iv => vec![2u8; block_size],
Pkcs12KeyType::Mac => vec![3u8; block_size],
};

let slen = block_size * ((salt.len() + block_size - 1) / block_size);
let plen = block_size * ((pass_utf16.len() + block_size - 1) / block_size);
let ilen = slen + plen;
let mut init_key = vec![0u8; ilen];
// 2. Concatenate copies of the salt together to create a string S of
// length v(ceiling(s/v)) bits (the final copy of the salt may be
// truncated to create S). Note that if the salt is the empty
// string, then so is S.
for i in 0..slen {
init_key[i] = salt[i % salt.len()];
}

// 3. Concatenate copies of the password together to create a string P
// of length v(ceiling(p/v)) bits (the final copy of the password
// may be truncated to create P). Note that if the password is the
// empty string, then so is P.
for i in 0..plen {
init_key[slen + i] = pass_utf16[i % pass_utf16.len()];
}
pass_utf16.zeroize();

let id_block = match id {
Pkcs12KeyType::EncryptionKey => vec![1u8; block_size],
Pkcs12KeyType::Iv => vec![2u8; block_size],
Pkcs12KeyType::Mac => vec![3u8; block_size],
};
// 4. Set I=S||P to be the concatenation of S and P.
// [already done in `init_key`]

let mut m = key_len;
let mut n = 0;
let mut out = vec![0u8; key_len];
// 5. Set c=ceiling(n/u)
// 6. For i=1, 2, ..., c, do the following:
// [ Instead of following this approach, we use an infinite loop and
// use the break condition below, if we have produced n bytes for the key]
loop {
// 6. A. Set A2=H^r(D||I). (i.e., the r-th hash of D||1,
// H(H(H(... H(D||I))))
<D as Update>::update(&mut digest, &id_block);
<D as Update>::update(&mut digest, &init_key);
let mut result = digest.finalize_fixed_reset();
for _ in 1..rounds {
<D as Update>::update(&mut digest, &result[0..output_size]);
result = digest.finalize_fixed_reset();
}

// 7. Concateate A_1, A_2, ..., A_c together to form a pseudorandom
// bit string, A.
// [ Instead of storing all Ais and concatenating later, we concatenate
// them immediately ]
let new_bytes_num = m.min(output_size);
out[n..n + new_bytes_num].copy_from_slice(&result[0..new_bytes_num]);
n += new_bytes_num;
if m <= new_bytes_num {
break;
}

// prepare `init_key` for next block if `ouput_size` is smaller than `key_len`
m -= new_bytes_num;

// 6. B. Concatenate copies of Ai to create a string B of length v
// bits (the final copy of Ai may be truncated to create B).
// [ we achieve this on thy fly with the expression `result[k % output_size]` below]

// 6. C. Treating I as a concatenation I_0, I_1, ..., I_(k-1) of v-bit
// blocks, where k=ceiling(s/v)+ceiling(p/v), modify I by
// setting I_j=(I_j+B+1) mod 2^v for each j.
let mut j = 0;
while j < ilen {
let mut c = 1_u16;
Expand All @@ -104,5 +140,6 @@ where
}
}
init_key.zeroize();
// 8. Use the first n bits of A as the output of this entire process.
out
}
5 changes: 1 addition & 4 deletions pkcs12/tests/kdf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@
/// All test cases have been verified against openssl's method `PKCS12_key_gen_utf8`.
/// See https://github.com/xemwebe/test_pkcs12_kdf for a sample program.
///

use hex_literal::hex;
use pkcs12::kdf::{derive_key, Pkcs12KeyType};

#[test]
fn pkcs12_key_derive_sha256() {
const PASS_SHORT: &str = "ge@äheim";
Expand Down Expand Up @@ -137,5 +136,3 @@ fn pkcs12_key_derive_special_chars() {
hex!("d01e72a940b4b1a7a5707fc8264a60cb7606ff9051dedff90930687d2513c006")
);
}


0 comments on commit 7537728

Please sign in to comment.