mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-26 14:24:46 +02:00
8301553: Support Password-Based Cryptography in SunPKCS11
Co-authored-by: Francisco Ferrari Bihurriet <fferrari@redhat.com> Co-authored-by: Martin Balao <mbalao@openjdk.org> Reviewed-by: valeriep
This commit is contained in:
parent
0a4f9ad637
commit
4a75fd462c
30 changed files with 3013 additions and 452 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -25,13 +25,14 @@
|
|||
|
||||
package com.sun.crypto.provider;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import javax.crypto.spec.PBEParameterSpec;
|
||||
import javax.crypto.spec.PBEKeySpec;
|
||||
import java.security.*;
|
||||
import java.security.spec.*;
|
||||
import java.util.Arrays;
|
||||
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
import sun.security.util.PBEUtil;
|
||||
|
||||
/**
|
||||
* This is an implementation of the HMAC algorithms as defined
|
||||
|
@ -108,81 +109,30 @@ abstract class HmacPKCS12PBECore extends HmacCore {
|
|||
*/
|
||||
protected void engineInit(Key key, AlgorithmParameterSpec params)
|
||||
throws InvalidKeyException, InvalidAlgorithmParameterException {
|
||||
char[] passwdChars;
|
||||
byte[] salt = null;
|
||||
int iCount = 0;
|
||||
if (key instanceof javax.crypto.interfaces.PBEKey) {
|
||||
javax.crypto.interfaces.PBEKey pbeKey =
|
||||
(javax.crypto.interfaces.PBEKey) key;
|
||||
passwdChars = pbeKey.getPassword();
|
||||
salt = pbeKey.getSalt(); // maybe null if unspecified
|
||||
iCount = pbeKey.getIterationCount(); // maybe 0 if unspecified
|
||||
} else if (key instanceof SecretKey) {
|
||||
byte[] passwdBytes;
|
||||
if (!(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3)) ||
|
||||
(passwdBytes = key.getEncoded()) == null) {
|
||||
throw new InvalidKeyException("Missing password");
|
||||
}
|
||||
passwdChars = new char[passwdBytes.length];
|
||||
for (int i=0; i<passwdChars.length; i++) {
|
||||
passwdChars[i] = (char) (passwdBytes[i] & 0x7f);
|
||||
}
|
||||
Arrays.fill(passwdBytes, (byte)0x00);
|
||||
} else {
|
||||
throw new InvalidKeyException("SecretKey of PBE type required");
|
||||
}
|
||||
|
||||
byte[] derivedKey;
|
||||
char[] password = null;
|
||||
byte[] derivedKey = null;
|
||||
SecretKeySpec cipherKey = null;
|
||||
PBEKeySpec keySpec = PBEUtil.getPBAKeySpec(key, params);
|
||||
try {
|
||||
if (params == null) {
|
||||
// should not auto-generate default values since current
|
||||
// javax.crypto.Mac api does not have any method for caller to
|
||||
// retrieve the generated defaults.
|
||||
if ((salt == null) || (iCount == 0)) {
|
||||
throw new InvalidAlgorithmParameterException
|
||||
("PBEParameterSpec required for salt and iteration count");
|
||||
}
|
||||
} else if (!(params instanceof PBEParameterSpec)) {
|
||||
throw new InvalidAlgorithmParameterException
|
||||
("PBEParameterSpec type required");
|
||||
} else {
|
||||
PBEParameterSpec pbeParams = (PBEParameterSpec) params;
|
||||
// make sure the parameter values are consistent
|
||||
if (salt != null) {
|
||||
if (!Arrays.equals(salt, pbeParams.getSalt())) {
|
||||
throw new InvalidAlgorithmParameterException
|
||||
("Inconsistent value of salt between key and params");
|
||||
}
|
||||
} else {
|
||||
salt = pbeParams.getSalt();
|
||||
}
|
||||
if (iCount != 0) {
|
||||
if (iCount != pbeParams.getIterationCount()) {
|
||||
throw new InvalidAlgorithmParameterException
|
||||
("Different iteration count between key and params");
|
||||
}
|
||||
} else {
|
||||
iCount = pbeParams.getIterationCount();
|
||||
}
|
||||
}
|
||||
// For security purpose, we need to enforce a minimum length
|
||||
// for salt; just require the minimum salt length to be 8-byte
|
||||
// which is what PKCS#5 recommends and openssl does.
|
||||
if (salt.length < 8) {
|
||||
throw new InvalidAlgorithmParameterException
|
||||
("Salt must be at least 8 bytes long");
|
||||
}
|
||||
if (iCount <= 0) {
|
||||
throw new InvalidAlgorithmParameterException
|
||||
("IterationCount must be a positive number");
|
||||
}
|
||||
derivedKey = PKCS12PBECipherCore.derive(passwdChars, salt,
|
||||
iCount, engineGetMacLength(), PKCS12PBECipherCore.MAC_KEY,
|
||||
algorithm, bl);
|
||||
password = keySpec.getPassword();
|
||||
derivedKey = PKCS12PBECipherCore.derive(
|
||||
password, keySpec.getSalt(),
|
||||
keySpec.getIterationCount(), engineGetMacLength(),
|
||||
PKCS12PBECipherCore.MAC_KEY, algorithm, bl);
|
||||
cipherKey = new SecretKeySpec(derivedKey, "HmacSHA1");
|
||||
super.engineInit(cipherKey, null);
|
||||
} finally {
|
||||
Arrays.fill(passwdChars, '\0');
|
||||
if (cipherKey != null) {
|
||||
SharedSecrets.getJavaxCryptoSpecAccess()
|
||||
.clearSecretKeySpec(cipherKey);
|
||||
}
|
||||
if (derivedKey != null) {
|
||||
Arrays.fill(derivedKey, (byte) 0);
|
||||
}
|
||||
if (password != null) {
|
||||
Arrays.fill(password, '\0');
|
||||
}
|
||||
keySpec.clearPassword();
|
||||
}
|
||||
SecretKey cipherKey = new SecretKeySpec(derivedKey, "HmacSHA1");
|
||||
super.engineInit(cipherKey, null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -31,6 +31,9 @@ import java.util.Arrays;
|
|||
import javax.crypto.*;
|
||||
import javax.crypto.spec.*;
|
||||
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
import sun.security.util.PBEUtil;
|
||||
|
||||
/**
|
||||
* This class represents password-based encryption as defined by the PKCS #5
|
||||
* standard.
|
||||
|
@ -43,10 +46,6 @@ import javax.crypto.spec.*;
|
|||
* @see javax.crypto.Cipher
|
||||
*/
|
||||
abstract class PBES2Core extends CipherSpi {
|
||||
|
||||
private static final int DEFAULT_SALT_LENGTH = 20;
|
||||
private static final int DEFAULT_COUNT = 4096;
|
||||
|
||||
// the encapsulated cipher
|
||||
private final CipherCore cipher;
|
||||
private final int keyLength; // in bits
|
||||
|
@ -54,9 +53,7 @@ abstract class PBES2Core extends CipherSpi {
|
|||
private final PBKDF2Core kdf;
|
||||
private final String pbeAlgo;
|
||||
private final String cipherAlgo;
|
||||
private int iCount = DEFAULT_COUNT;
|
||||
private byte[] salt = null;
|
||||
private IvParameterSpec ivSpec = null;
|
||||
private final PBEUtil.PBES2Params pbes2Params = new PBEUtil.PBES2Params();
|
||||
|
||||
/**
|
||||
* Creates an instance of PBE Scheme 2 according to the selected
|
||||
|
@ -135,32 +132,8 @@ abstract class PBES2Core extends CipherSpi {
|
|||
}
|
||||
|
||||
protected AlgorithmParameters engineGetParameters() {
|
||||
AlgorithmParameters params = null;
|
||||
if (salt == null) {
|
||||
// generate random salt and use default iteration count
|
||||
salt = new byte[DEFAULT_SALT_LENGTH];
|
||||
SunJCE.getRandom().nextBytes(salt);
|
||||
iCount = DEFAULT_COUNT;
|
||||
}
|
||||
if (ivSpec == null) {
|
||||
// generate random IV
|
||||
byte[] ivBytes = new byte[blkSize];
|
||||
SunJCE.getRandom().nextBytes(ivBytes);
|
||||
ivSpec = new IvParameterSpec(ivBytes);
|
||||
}
|
||||
PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, iCount, ivSpec);
|
||||
try {
|
||||
params = AlgorithmParameters.getInstance(pbeAlgo,
|
||||
SunJCE.getInstance());
|
||||
params.init(pbeSpec);
|
||||
} catch (NoSuchAlgorithmException nsae) {
|
||||
// should never happen
|
||||
throw new RuntimeException("SunJCE called, but not configured");
|
||||
} catch (InvalidParameterSpecException ipse) {
|
||||
// should never happen
|
||||
throw new RuntimeException("PBEParameterSpec not supported");
|
||||
}
|
||||
return params;
|
||||
return pbes2Params.getAlgorithmParameters(
|
||||
blkSize, pbeAlgo, SunJCE.getInstance(), SunJCE.getRandom());
|
||||
}
|
||||
|
||||
protected void engineInit(int opmode, Key key, SecureRandom random)
|
||||
|
@ -172,132 +145,46 @@ abstract class PBES2Core extends CipherSpi {
|
|||
}
|
||||
}
|
||||
|
||||
private static byte[] check(byte[] salt)
|
||||
throws InvalidAlgorithmParameterException {
|
||||
if (salt != null && salt.length < 8) {
|
||||
throw new InvalidAlgorithmParameterException(
|
||||
"Salt must be at least 8 bytes long");
|
||||
}
|
||||
return salt;
|
||||
}
|
||||
|
||||
private static int check(int iCount)
|
||||
throws InvalidAlgorithmParameterException {
|
||||
if (iCount < 0) {
|
||||
throw new InvalidAlgorithmParameterException(
|
||||
"Iteration count must be a positive number");
|
||||
}
|
||||
return iCount == 0 ? DEFAULT_COUNT : iCount;
|
||||
}
|
||||
|
||||
protected void engineInit(int opmode, Key key,
|
||||
AlgorithmParameterSpec params,
|
||||
SecureRandom random)
|
||||
throws InvalidKeyException, InvalidAlgorithmParameterException {
|
||||
|
||||
if (key == null) {
|
||||
throw new InvalidKeyException("Null key");
|
||||
}
|
||||
|
||||
byte[] passwdBytes = key.getEncoded();
|
||||
char[] passwdChars = null;
|
||||
salt = null;
|
||||
iCount = 0;
|
||||
ivSpec = null;
|
||||
|
||||
PBEKeySpec pbeSpec;
|
||||
try {
|
||||
if ((passwdBytes == null) ||
|
||||
!(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3))) {
|
||||
throw new InvalidKeyException("Missing password");
|
||||
}
|
||||
|
||||
boolean doEncrypt = ((opmode == Cipher.ENCRYPT_MODE) ||
|
||||
(opmode == Cipher.WRAP_MODE));
|
||||
|
||||
// Extract from the supplied PBE params, if present
|
||||
if (params instanceof PBEParameterSpec pbeParams) {
|
||||
// salt should be non-null per PBEParameterSpec
|
||||
salt = check(pbeParams.getSalt());
|
||||
iCount = check(pbeParams.getIterationCount());
|
||||
AlgorithmParameterSpec ivParams = pbeParams.getParameterSpec();
|
||||
if (ivParams instanceof IvParameterSpec iv) {
|
||||
ivSpec = iv;
|
||||
} else if (ivParams == null && doEncrypt) {
|
||||
// generate random IV
|
||||
byte[] ivBytes = new byte[blkSize];
|
||||
random.nextBytes(ivBytes);
|
||||
ivSpec = new IvParameterSpec(ivBytes);
|
||||
} else {
|
||||
throw new InvalidAlgorithmParameterException(
|
||||
"Wrong parameter type: IV expected");
|
||||
}
|
||||
} else if (params == null && doEncrypt) {
|
||||
// Try extracting from the key if present. If unspecified,
|
||||
// PBEKey returns null and 0 respectively.
|
||||
if (key instanceof javax.crypto.interfaces.PBEKey pbeKey) {
|
||||
salt = check(pbeKey.getSalt());
|
||||
iCount = check(pbeKey.getIterationCount());
|
||||
}
|
||||
if (salt == null) {
|
||||
// generate random salt
|
||||
salt = new byte[DEFAULT_SALT_LENGTH];
|
||||
random.nextBytes(salt);
|
||||
}
|
||||
if (iCount == 0) {
|
||||
// use default iteration count
|
||||
iCount = DEFAULT_COUNT;
|
||||
}
|
||||
// generate random IV
|
||||
byte[] ivBytes = new byte[blkSize];
|
||||
random.nextBytes(ivBytes);
|
||||
ivSpec = new IvParameterSpec(ivBytes);
|
||||
} else {
|
||||
throw new InvalidAlgorithmParameterException
|
||||
("Wrong parameter type: PBE expected");
|
||||
}
|
||||
passwdChars = new char[passwdBytes.length];
|
||||
for (int i = 0; i < passwdChars.length; i++)
|
||||
passwdChars[i] = (char) (passwdBytes[i] & 0x7f);
|
||||
|
||||
pbeSpec = new PBEKeySpec(passwdChars, salt, iCount, keyLength);
|
||||
} finally {
|
||||
// password char[] was cloned in PBEKeySpec constructor,
|
||||
// so we can zero it out here
|
||||
if (passwdChars != null) Arrays.fill(passwdChars, '\0');
|
||||
if (passwdBytes != null) Arrays.fill(passwdBytes, (byte)0x00);
|
||||
}
|
||||
|
||||
PBKDF2KeyImpl s;
|
||||
|
||||
PBEKeySpec pbeSpec = pbes2Params.getPBEKeySpec(blkSize, keyLength,
|
||||
opmode, key, params, random);
|
||||
PBKDF2KeyImpl s = null;
|
||||
byte[] derivedKey;
|
||||
try {
|
||||
s = (PBKDF2KeyImpl)kdf.engineGenerateSecret(pbeSpec);
|
||||
derivedKey = s.getEncoded();
|
||||
} catch (InvalidKeySpecException ikse) {
|
||||
throw new InvalidKeyException("Cannot construct PBE key", ikse);
|
||||
} finally {
|
||||
if (s != null) {
|
||||
s.clear();
|
||||
}
|
||||
pbeSpec.clearPassword();
|
||||
}
|
||||
byte[] derivedKey = s.getEncoded();
|
||||
s.clearPassword();
|
||||
SecretKeySpec cipherKey = new SecretKeySpec(derivedKey, cipherAlgo);
|
||||
|
||||
// initialize the underlying cipher
|
||||
cipher.init(opmode, cipherKey, ivSpec, random);
|
||||
SecretKeySpec cipherKey = null;
|
||||
try {
|
||||
cipherKey = new SecretKeySpec(derivedKey, cipherAlgo);
|
||||
// initialize the underlying cipher
|
||||
cipher.init(opmode, cipherKey, pbes2Params.getIvSpec(), random);
|
||||
} finally {
|
||||
if (cipherKey != null) {
|
||||
SharedSecrets.getJavaxCryptoSpecAccess()
|
||||
.clearSecretKeySpec(cipherKey);
|
||||
}
|
||||
Arrays.fill(derivedKey, (byte) 0);
|
||||
}
|
||||
}
|
||||
|
||||
protected void engineInit(int opmode, Key key, AlgorithmParameters params,
|
||||
SecureRandom random)
|
||||
throws InvalidKeyException, InvalidAlgorithmParameterException {
|
||||
AlgorithmParameterSpec pbeSpec = null;
|
||||
if (params != null) {
|
||||
try {
|
||||
pbeSpec = params.getParameterSpec(PBEParameterSpec.class);
|
||||
} catch (InvalidParameterSpecException ipse) {
|
||||
throw new InvalidAlgorithmParameterException(
|
||||
"Wrong parameter type: PBE expected");
|
||||
}
|
||||
}
|
||||
engineInit(opmode, key, pbeSpec, random);
|
||||
engineInit(opmode, key, PBEUtil.PBES2Params.getParameterSpec(params),
|
||||
random);
|
||||
}
|
||||
|
||||
protected byte[] engineUpdate(byte[] input, int inputOffset, int inputLen) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -26,7 +26,7 @@
|
|||
package com.sun.crypto.provider;
|
||||
|
||||
import java.io.ObjectStreamException;
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.Cleaner;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.CharBuffer;
|
||||
import java.util.Arrays;
|
||||
|
@ -64,9 +64,9 @@ final class PBKDF2KeyImpl implements javax.crypto.interfaces.PBEKey {
|
|||
private int iterCount;
|
||||
private byte[] key;
|
||||
|
||||
@SuppressWarnings("serial") // Type of field is not Serializable;
|
||||
// see writeReplace method
|
||||
private Mac prf;
|
||||
// The following fields are not Serializable. See writeReplace method.
|
||||
private transient Mac prf;
|
||||
private transient Cleaner.Cleanable cleaner;
|
||||
|
||||
private static byte[] getPasswordBytes(char[] passwd) {
|
||||
CharBuffer cb = CharBuffer.wrap(passwd);
|
||||
|
@ -88,17 +88,9 @@ final class PBKDF2KeyImpl implements javax.crypto.interfaces.PBEKey {
|
|||
*/
|
||||
PBKDF2KeyImpl(PBEKeySpec keySpec, String prfAlgo)
|
||||
throws InvalidKeySpecException {
|
||||
char[] passwd = keySpec.getPassword();
|
||||
if (passwd == null) {
|
||||
// Should allow an empty password.
|
||||
this.passwd = new char[0];
|
||||
} else {
|
||||
this.passwd = passwd.clone();
|
||||
}
|
||||
this.passwd = keySpec.getPassword();
|
||||
// Convert the password from char[] to byte[]
|
||||
byte[] passwdBytes = getPasswordBytes(this.passwd);
|
||||
// remove local copy
|
||||
if (passwd != null) Arrays.fill(passwd, '\0');
|
||||
|
||||
try {
|
||||
this.salt = keySpec.getSalt();
|
||||
|
@ -124,16 +116,18 @@ final class PBKDF2KeyImpl implements javax.crypto.interfaces.PBEKey {
|
|||
throw new InvalidKeySpecException(nsae);
|
||||
} finally {
|
||||
Arrays.fill(passwdBytes, (byte) 0x00);
|
||||
|
||||
// Use the cleaner to zero the key when no longer referenced
|
||||
final byte[] k = this.key;
|
||||
final char[] p = this.passwd;
|
||||
CleanerFactory.cleaner().register(this,
|
||||
() -> {
|
||||
Arrays.fill(k, (byte) 0x00);
|
||||
Arrays.fill(p, '\0');
|
||||
});
|
||||
if (key == null) {
|
||||
Arrays.fill(passwd, '\0');
|
||||
}
|
||||
}
|
||||
// Use the cleaner to zero the key when no longer referenced
|
||||
final byte[] k = this.key;
|
||||
final char[] p = this.passwd;
|
||||
cleaner = CleanerFactory.cleaner().register(this,
|
||||
() -> {
|
||||
Arrays.fill(k, (byte) 0x00);
|
||||
Arrays.fill(p, '\0');
|
||||
});
|
||||
}
|
||||
|
||||
private static byte[] deriveKey(final Mac prf, final byte[] password,
|
||||
|
@ -211,11 +205,7 @@ final class PBKDF2KeyImpl implements javax.crypto.interfaces.PBEKey {
|
|||
}
|
||||
|
||||
public byte[] getEncoded() {
|
||||
// The key is zeroized by finalize()
|
||||
// The reachability fence ensures finalize() isn't called early
|
||||
byte[] result = key.clone();
|
||||
Reference.reachabilityFence(this);
|
||||
return result;
|
||||
return key.clone();
|
||||
}
|
||||
|
||||
public String getAlgorithm() {
|
||||
|
@ -226,16 +216,12 @@ final class PBKDF2KeyImpl implements javax.crypto.interfaces.PBEKey {
|
|||
return iterCount;
|
||||
}
|
||||
|
||||
public void clearPassword() {
|
||||
Arrays.fill(passwd, (char)0);
|
||||
public void clear() {
|
||||
cleaner.clean();
|
||||
}
|
||||
|
||||
public char[] getPassword() {
|
||||
// The password is zeroized by finalize()
|
||||
// The reachability fence ensures finalize() isn't called early
|
||||
char[] result = passwd.clone();
|
||||
Reference.reachabilityFence(this);
|
||||
return result;
|
||||
return passwd.clone();
|
||||
}
|
||||
|
||||
public byte[] getSalt() {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -25,6 +25,8 @@
|
|||
|
||||
package com.sun.crypto.provider;
|
||||
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
|
@ -179,23 +181,29 @@ abstract class PBMAC1Core extends HmacCore {
|
|||
}
|
||||
|
||||
PBKDF2KeyImpl s = null;
|
||||
PBKDF2Core kdf = getKDFImpl(kdfAlgo);
|
||||
byte[] derivedKey;
|
||||
byte[] derivedKey = null;
|
||||
SecretKeySpec cipherKey = null;
|
||||
try {
|
||||
PBKDF2Core kdf = getKDFImpl(kdfAlgo);
|
||||
s = (PBKDF2KeyImpl)kdf.engineGenerateSecret(pbeSpec);
|
||||
derivedKey = s.getEncoded();
|
||||
cipherKey = new SecretKeySpec(derivedKey, kdfAlgo);
|
||||
super.engineInit(cipherKey, null);
|
||||
} catch (InvalidKeySpecException ikse) {
|
||||
throw new InvalidKeyException("Cannot construct PBE key", ikse);
|
||||
} finally {
|
||||
pbeSpec.clearPassword();
|
||||
if (s != null) {
|
||||
s.clearPassword();
|
||||
if (cipherKey != null) {
|
||||
SharedSecrets.getJavaxCryptoSpecAccess()
|
||||
.clearSecretKeySpec(cipherKey);
|
||||
}
|
||||
if (derivedKey != null) {
|
||||
Arrays.fill(derivedKey, (byte) 0);
|
||||
}
|
||||
if (s != null) {
|
||||
s.clear();
|
||||
}
|
||||
pbeSpec.clearPassword();
|
||||
}
|
||||
SecretKey cipherKey = new SecretKeySpec(derivedKey, kdfAlgo);
|
||||
Arrays.fill(derivedKey, (byte)0);
|
||||
|
||||
super.engineInit(cipherKey, null);
|
||||
}
|
||||
|
||||
public static final class HmacSHA1 extends PBMAC1Core {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue