//! Password-Based Encryption Scheme 2 tests

use der::Encode;
use hex_literal::hex;
use pkcs5::pbes2;

/// PBES2 + PBKDF2-SHA1 + AES-128-CBC `AlgorithmIdentifier` example.
///
/// Generated by OpenSSL and extracted from the `pkcs8` crate's
/// `tests/examples/ed25519-encpriv-aes128-pbkdf2-sha1.der` test vector.
const PBES2_PBKDF2_SHA1_AES128CBC_ALG_ID: &[u8] = &hex!(
    "304906092a864886f70d01050d303c301b06092a864886f70d01050c300e0408
     e8765e01e43b6bad02020800301d06096086480165030401020410223080a71b
     cd2b9a256d876c924979d2"
);

/// PBES2 + PBKDF2-SHA256 + AES-256-CBC `AlgorithmIdentifier` example.
///
/// Generated by OpenSSL and extracted from the `pkcs8` crate's
/// `tests/examples/ed25519-encpriv-aes256-pbkdf2-sha256.der` test vector.
const PBES2_PBKDF2_SHA256_AES256CBC_ALG_ID: &[u8] = &hex!(
    "305706092a864886f70d01050d304a302906092a864886f70d01050c301c0408
     79d982e70df91a8802020800300c06082a864886f70d02090500301d06096086
     4801650304012a0410b2d02d78b2efd9dff694cf8e0af40925"
);

/// PBES2 + scrypt + AES-256-CBC `AlgorithmIdentifier` example.
///
/// Generated by OpenSSL and extracted from the `pkcs8` crate's
/// `ed25519-encpriv-aes256-scrypt.der` test vector.
const PBES2_SCRYPT_AES256CBC_ALG_ID: &[u8] = &hex!(
    "304f06092a864886f70d01050d3042302106092b06010401da47040b30140408
    e6211e2348ad69e002024000020108020101301d060960864801650304012a041
    09bd0a6251f2254f9fd5963887c27cf01"
);

/// PBES2 + DES-EDE3-CBC + PBKDF-SHA2 `AlgorithmIdentifier` example.
///
/// Generated by OpenSSL and extracted from the `pkcs8` crate's
/// `ed25519-encpriv-des3-pbkdf-sha256.der` test vector.
#[cfg(feature = "3des")]
const PBES2_PBKDF2_SHA256_DESEDE3CBC_ALG_ID: &[u8] = &hex!(
    "304e06092a864886f70d01050d 3041302906092a864886f70d01050c301c0408
    32a0ae2e01bbe32902020800300c06082a864886f70d02090500301406 082a864
    886f70d0307040897e8f53ab0aca359"
);

/// PBES2 + DES-CBC + PBKDF-SHA2 `AlgorithmIdentifier` example.
///
/// Generated by OpenSSL and extracted from the `pkcs8` crate's
/// `ed25519-encpriv-des-pbkdf-sha256.der` test vector.
#[cfg(feature = "des-insecure")]
const PBES2_PBKDF2_SHA256_DESCBC_ALG_ID: &[u8] = &hex!(
    "304b06092a864886f70d01050d303e302906092a864886f70d01050c301c04080
    9e7edfbd9f21e2b02020800300c06082a864886f70d02090500301106052b0e030
    2070408f4aaf206a18de7ad"
);

/// Decoding test for PBES2 + PBKDF2-SHA1 + AES-128-CBC `AlgorithmIdentifier`
#[test]
fn decode_pbes2_pbkdf2_sha1_aes128cbc() {
    let scheme = pkcs5::EncryptionScheme::try_from(PBES2_PBKDF2_SHA1_AES128CBC_ALG_ID).unwrap();
    let params = scheme.pbes2().unwrap();

    let pbkdf2_params = params.kdf.pbkdf2().unwrap();
    assert_eq!(pbkdf2_params.salt, &hex!("e8765e01e43b6bad"));
    assert_eq!(pbkdf2_params.iteration_count, 2048);
    assert_eq!(pbkdf2_params.key_length, None);
    assert_eq!(pbkdf2_params.prf, pbes2::Pbkdf2Prf::HmacWithSha1);

    match params.encryption {
        pbes2::EncryptionScheme::Aes128Cbc { iv } => {
            assert_eq!(iv, &hex!("223080a71bcd2b9a256d876c924979d2"));
        }
        other => panic!("unexpected encryption scheme: {:?}", other),
    }
}

/// Decoding test for PBES2 + PBKDF2-SHA256 + AES-256-CBC `AlgorithmIdentifier`
#[test]
fn decode_pbes2_pbkdf2_sha256_aes256cbc() {
    let scheme = pkcs5::EncryptionScheme::try_from(PBES2_PBKDF2_SHA256_AES256CBC_ALG_ID).unwrap();
    let params = scheme.pbes2().unwrap();

    let pbkdf2_params = params.kdf.pbkdf2().unwrap();
    assert_eq!(pbkdf2_params.salt, &hex!("79d982e70df91a88"));
    assert_eq!(pbkdf2_params.iteration_count, 2048);
    assert_eq!(pbkdf2_params.key_length, None);
    assert_eq!(pbkdf2_params.prf, pbes2::Pbkdf2Prf::HmacWithSha256);

    match params.encryption {
        pbes2::EncryptionScheme::Aes256Cbc { iv } => {
            assert_eq!(iv, &hex!("b2d02d78b2efd9dff694cf8e0af40925"));
        }
        other => panic!("unexpected encryption scheme: {:?}", other),
    }
}

/// Decoding test for PBES2 + scrypt + AES-256-CBC `AlgorithmIdentifier`
#[test]
fn decode_pbes2_scrypt_aes256cbc() {
    let scheme = pkcs5::EncryptionScheme::try_from(PBES2_SCRYPT_AES256CBC_ALG_ID).unwrap();
    let params = scheme.pbes2().unwrap();

    let scrypt_params = params.kdf.scrypt().unwrap();
    assert_eq!(scrypt_params.salt, &hex!("E6211E2348AD69E0"));
    assert_eq!(scrypt_params.cost_parameter, 16384);
    assert_eq!(scrypt_params.block_size, 8);
    assert_eq!(scrypt_params.parallelization, 1);
    assert_eq!(scrypt_params.key_length, None);

    match params.encryption {
        pbes2::EncryptionScheme::Aes256Cbc { iv } => {
            assert_eq!(iv, &hex!("9BD0A6251F2254F9FD5963887C27CF01"));
        }
        other => panic!("unexpected encryption scheme: {:?}", other),
    }
}

/// Decoding test for PBES2 + PBKDF2-SHA256 + DES-EDE3-CBC `AlgorithmIdentifier`
#[cfg(feature = "3des")]
#[test]
fn decode_pbes2_pbkdf2_sha256_desede3cbc() {
    let scheme = pkcs5::EncryptionScheme::try_from(PBES2_PBKDF2_SHA256_DESEDE3CBC_ALG_ID).unwrap();
    let params = scheme.pbes2().unwrap();

    let pbkdf2_params = params.kdf.pbkdf2().unwrap();
    assert_eq!(pbkdf2_params.salt, &hex!("32A0AE2E01BBE329"));
    assert_eq!(pbkdf2_params.key_length, None);
    assert_eq!(pbkdf2_params.prf, pbes2::Pbkdf2Prf::HmacWithSha256);
    assert_eq!(pbkdf2_params.iteration_count, 2048);

    match params.encryption {
        pbes2::EncryptionScheme::DesEde3Cbc { iv } => {
            assert_eq!(iv, &hex!("97E8F53AB0ACA359"));
        }
        other => panic!("unexpected encryption scheme: {:?}", other),
    }
}

/// Decoding test for PBES2 + PBKDF2-SHA256 + DES-CBC `AlgorithmIdentifier`
#[cfg(feature = "des-insecure")]
#[test]
fn decode_pbes2_pbkdf2_sha256_descbc() {
    let scheme = pkcs5::EncryptionScheme::try_from(PBES2_PBKDF2_SHA256_DESCBC_ALG_ID).unwrap();
    let params = scheme.pbes2().unwrap();

    let pbkdf2_params = params.kdf.pbkdf2().unwrap();
    assert_eq!(pbkdf2_params.salt, &hex!("09E7EDFBD9F21E2B"));
    assert_eq!(pbkdf2_params.key_length, None);
    assert_eq!(pbkdf2_params.prf, pbes2::Pbkdf2Prf::HmacWithSha256);
    assert_eq!(pbkdf2_params.iteration_count, 2048);

    match params.encryption {
        pbes2::EncryptionScheme::DesCbc { iv } => {
            assert_eq!(iv, &hex!("F4AAF206A18DE7AD"));
        }
        other => panic!("unexpected encryption scheme: {:?}", other),
    }
}

/// Encoding test for PBES2 + PBKDF2-SHA1 + AES-128-CBC `AlgorithmIdentifier`
#[test]
fn encode_pbes2_pbkdf2_sha1_aes128cbc() {
    let mut buffer = [0u8; 1024];

    let scheme = pkcs5::EncryptionScheme::try_from(PBES2_PBKDF2_SHA1_AES128CBC_ALG_ID).unwrap();
    let mut encoder = der::SliceWriter::new(&mut buffer);
    scheme.encode(&mut encoder).unwrap();

    let encoded_der = encoder.finish().unwrap();
    assert_eq!(encoded_der, PBES2_PBKDF2_SHA1_AES128CBC_ALG_ID);
}

/// Encoding test for PBES2 + PBKDF2-SHA256 + AES-256-CBC `AlgorithmIdentifier`
#[test]
fn encode_pbes2_pbkdf2_sha256_aes256cbc() {
    let mut buffer = [0u8; 1024];

    let scheme = pkcs5::EncryptionScheme::try_from(PBES2_PBKDF2_SHA256_AES256CBC_ALG_ID).unwrap();
    let mut encoder = der::SliceWriter::new(&mut buffer);
    scheme.encode(&mut encoder).unwrap();

    let encoded_der = encoder.finish().unwrap();
    assert_eq!(encoded_der, PBES2_PBKDF2_SHA256_AES256CBC_ALG_ID);
}

/// Encoding test for PBES2 + scrypt + AES-256-CBC `AlgorithmIdentifier`
#[test]
fn encode_pbes2_scrypt_aes256cbc() {
    let mut buffer = [0u8; 1024];

    let scheme = pkcs5::EncryptionScheme::try_from(PBES2_SCRYPT_AES256CBC_ALG_ID).unwrap();
    let mut encoder = der::SliceWriter::new(&mut buffer);
    scheme.encode(&mut encoder).unwrap();

    let encoded_der = encoder.finish().unwrap();
    assert_eq!(encoded_der, PBES2_SCRYPT_AES256CBC_ALG_ID);
}
