8258915: Temporary buffer cleanup
Reviewed-by: valeriep
This commit is contained in:
parent
31d8a19e47
commit
f834557ae0
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2021, 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
|
||||
@ -40,6 +40,7 @@ import java.security.NoSuchAlgorithmException;
|
||||
import java.security.ProviderException;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.spec.AlgorithmParameterSpec;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* This class implements the AES algorithm in its various modes
|
||||
@ -163,9 +164,12 @@ abstract class AESCipher extends CipherSpi {
|
||||
byte[] value = key.getEncoded();
|
||||
if (value == null) {
|
||||
throw new InvalidKeyException("Key encoding must not be null");
|
||||
} else if (value.length != fixedKeySize) {
|
||||
throw new InvalidKeyException("The key must be " +
|
||||
fixedKeySize + " bytes");
|
||||
} else {
|
||||
Arrays.fill(value, (byte)0);
|
||||
if (value.length != fixedKeySize) {
|
||||
throw new InvalidKeyException("The key must be " +
|
||||
fixedKeySize + " bytes");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -515,6 +519,7 @@ abstract class AESCipher extends CipherSpi {
|
||||
*/
|
||||
protected int engineGetKeySize(Key key) throws InvalidKeyException {
|
||||
byte[] encoded = key.getEncoded();
|
||||
Arrays.fill(encoded, (byte)0);
|
||||
if (!AESCrypt.isKeySizeValid(encoded.length)) {
|
||||
throw new InvalidKeyException("Invalid AES key length: " +
|
||||
encoded.length + " bytes");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2021, 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
|
||||
@ -94,6 +94,9 @@ final class AESCrypt extends SymmetricCipher implements AESConstants
|
||||
if (!MessageDigest.isEqual(key, lastKey)) {
|
||||
// re-generate session key 'sessionK' when cipher key changes
|
||||
makeSessionKey(key);
|
||||
if (lastKey != null) {
|
||||
Arrays.fill(lastKey, (byte)0);
|
||||
}
|
||||
lastKey = key.clone(); // save cipher key
|
||||
}
|
||||
|
||||
@ -673,12 +676,23 @@ final class AESCrypt extends SymmetricCipher implements AESConstants
|
||||
// and expand them into arrays of ints.
|
||||
int[] expandedKe = expandToSubKey(Ke, false); // decrypting==false
|
||||
int[] expandedKd = expandToSubKey(Kd, true); // decrypting==true
|
||||
|
||||
Arrays.fill(tk, 0);
|
||||
for (int[] ia: Ke) {
|
||||
Arrays.fill(ia, 0);
|
||||
}
|
||||
for (int[] ia: Kd) {
|
||||
Arrays.fill(ia, 0);
|
||||
}
|
||||
ROUNDS_12 = (ROUNDS>=12);
|
||||
ROUNDS_14 = (ROUNDS==14);
|
||||
limit = ROUNDS*4;
|
||||
|
||||
// store the expanded sub keys into 'sessionK'
|
||||
if (sessionK != null) {
|
||||
// erase the previous values in sessionK
|
||||
Arrays.fill(sessionK[0], 0);
|
||||
Arrays.fill(sessionK[1], 0);
|
||||
}
|
||||
sessionK = new int[][] { expandedKe, expandedKd };
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2021, 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
|
||||
@ -30,6 +30,7 @@ import java.security.InvalidParameterException;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.spec.AlgorithmParameterSpec;
|
||||
import java.util.Arrays;
|
||||
import javax.crypto.KeyGeneratorSpi;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
@ -112,6 +113,7 @@ public final class AESKeyGenerator extends KeyGeneratorSpi {
|
||||
byte[] keyBytes = new byte[keySize];
|
||||
this.random.nextBytes(keyBytes);
|
||||
aesKey = new SecretKeySpec(keyBytes, "AES");
|
||||
Arrays.fill(keyBytes, (byte)0);
|
||||
return aesKey;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2004, 2021, 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
|
||||
@ -198,7 +198,12 @@ abstract class AESWrapCipher extends CipherSpi {
|
||||
"only be used for key wrapping and unwrapping");
|
||||
}
|
||||
AESCipher.checkKeySize(key, fixedKeySize);
|
||||
cipher.init(decrypting, key.getAlgorithm(), key.getEncoded());
|
||||
byte[] encoded = key.getEncoded();
|
||||
try {
|
||||
cipher.init(decrypting, key.getAlgorithm(), encoded);
|
||||
} finally {
|
||||
Arrays.fill(encoded, (byte)0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -374,6 +379,7 @@ abstract class AESWrapCipher extends CipherSpi {
|
||||
*/
|
||||
protected int engineGetKeySize(Key key) throws InvalidKeyException {
|
||||
byte[] encoded = key.getEncoded();
|
||||
Arrays.fill(encoded, (byte)0);
|
||||
if (!AESCrypt.isKeySizeValid(encoded.length)) {
|
||||
throw new InvalidKeyException("Invalid key length: " +
|
||||
encoded.length + " bytes");
|
||||
@ -404,38 +410,42 @@ abstract class AESWrapCipher extends CipherSpi {
|
||||
throw new InvalidKeyException("Cannot get an encoding of " +
|
||||
"the key to be wrapped");
|
||||
}
|
||||
byte[] out = new byte[Math.addExact(keyVal.length, 8)];
|
||||
try {
|
||||
byte[] out = new byte[Math.addExact(keyVal.length, 8)];
|
||||
|
||||
if (keyVal.length == 8) {
|
||||
System.arraycopy(IV, 0, out, 0, IV.length);
|
||||
System.arraycopy(keyVal, 0, out, IV.length, 8);
|
||||
cipher.encryptBlock(out, 0, out, 0);
|
||||
} else {
|
||||
if (keyVal.length % 8 != 0) {
|
||||
throw new IllegalBlockSizeException("length of the " +
|
||||
"to be wrapped key should be multiples of 8 bytes");
|
||||
}
|
||||
System.arraycopy(IV, 0, out, 0, IV.length);
|
||||
System.arraycopy(keyVal, 0, out, IV.length, keyVal.length);
|
||||
int N = keyVal.length/8;
|
||||
byte[] buffer = new byte[blksize];
|
||||
for (int j = 0; j < 6; j++) {
|
||||
for (int i = 1; i <= N; i++) {
|
||||
int T = i + j*N;
|
||||
System.arraycopy(out, 0, buffer, 0, IV.length);
|
||||
System.arraycopy(out, i*8, buffer, IV.length, 8);
|
||||
cipher.encryptBlock(buffer, 0, buffer, 0);
|
||||
for (int k = 1; T != 0; k++) {
|
||||
byte v = (byte) T;
|
||||
buffer[IV.length - k] ^= v;
|
||||
T >>>= 8;
|
||||
if (keyVal.length == 8) {
|
||||
System.arraycopy(IV, 0, out, 0, IV.length);
|
||||
System.arraycopy(keyVal, 0, out, IV.length, 8);
|
||||
cipher.encryptBlock(out, 0, out, 0);
|
||||
} else {
|
||||
if (keyVal.length % 8 != 0) {
|
||||
throw new IllegalBlockSizeException("length of the " +
|
||||
"to be wrapped key should be multiples of 8 bytes");
|
||||
}
|
||||
System.arraycopy(IV, 0, out, 0, IV.length);
|
||||
System.arraycopy(keyVal, 0, out, IV.length, keyVal.length);
|
||||
int N = keyVal.length / 8;
|
||||
byte[] buffer = new byte[blksize];
|
||||
for (int j = 0; j < 6; j++) {
|
||||
for (int i = 1; i <= N; i++) {
|
||||
int T = i + j * N;
|
||||
System.arraycopy(out, 0, buffer, 0, IV.length);
|
||||
System.arraycopy(out, i * 8, buffer, IV.length, 8);
|
||||
cipher.encryptBlock(buffer, 0, buffer, 0);
|
||||
for (int k = 1; T != 0; k++) {
|
||||
byte v = (byte) T;
|
||||
buffer[IV.length - k] ^= v;
|
||||
T >>>= 8;
|
||||
}
|
||||
System.arraycopy(buffer, 0, out, 0, IV.length);
|
||||
System.arraycopy(buffer, 8, out, 8 * i, 8);
|
||||
}
|
||||
System.arraycopy(buffer, 0, out, 0, IV.length);
|
||||
System.arraycopy(buffer, 8, out, 8*i, 8);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
} finally {
|
||||
Arrays.fill(keyVal, (byte)0);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -474,38 +484,43 @@ abstract class AESWrapCipher extends CipherSpi {
|
||||
}
|
||||
byte[] out = new byte[wrappedKeyLen - 8];
|
||||
byte[] buffer = new byte[blksize];
|
||||
if (wrappedKeyLen == 16) {
|
||||
cipher.decryptBlock(wrappedKey, 0, buffer, 0);
|
||||
for (int i = 0; i < IV.length; i++) {
|
||||
if (IV[i] != buffer[i]) {
|
||||
throw new InvalidKeyException("Integrity check failed");
|
||||
}
|
||||
}
|
||||
System.arraycopy(buffer, IV.length, out, 0, out.length);
|
||||
} else {
|
||||
System.arraycopy(wrappedKey, 0, buffer, 0, IV.length);
|
||||
System.arraycopy(wrappedKey, IV.length, out, 0, out.length);
|
||||
int N = out.length/8;
|
||||
for (int j = 5; j >= 0; j--) {
|
||||
for (int i = N; i > 0; i--) {
|
||||
int T = i + j*N;
|
||||
System.arraycopy(out, 8*(i-1), buffer, IV.length, 8);
|
||||
for (int k = 1; T != 0; k++) {
|
||||
byte v = (byte) T;
|
||||
buffer[IV.length - k] ^= v;
|
||||
T >>>= 8;
|
||||
try {
|
||||
if (wrappedKeyLen == 16) {
|
||||
cipher.decryptBlock(wrappedKey, 0, buffer, 0);
|
||||
for (int i = 0; i < IV.length; i++) {
|
||||
if (IV[i] != buffer[i]) {
|
||||
throw new InvalidKeyException("Integrity check failed");
|
||||
}
|
||||
}
|
||||
System.arraycopy(buffer, IV.length, out, 0, out.length);
|
||||
} else {
|
||||
System.arraycopy(wrappedKey, 0, buffer, 0, IV.length);
|
||||
System.arraycopy(wrappedKey, IV.length, out, 0, out.length);
|
||||
int N = out.length / 8;
|
||||
for (int j = 5; j >= 0; j--) {
|
||||
for (int i = N; i > 0; i--) {
|
||||
int T = i + j * N;
|
||||
System.arraycopy(out, 8 * (i - 1), buffer, IV.length, 8);
|
||||
for (int k = 1; T != 0; k++) {
|
||||
byte v = (byte) T;
|
||||
buffer[IV.length - k] ^= v;
|
||||
T >>>= 8;
|
||||
}
|
||||
cipher.decryptBlock(buffer, 0, buffer, 0);
|
||||
System.arraycopy(buffer, IV.length, out, 8 * (i - 1), 8);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < IV.length; i++) {
|
||||
if (IV[i] != buffer[i]) {
|
||||
throw new InvalidKeyException("Integrity check failed");
|
||||
}
|
||||
cipher.decryptBlock(buffer, 0, buffer, 0);
|
||||
System.arraycopy(buffer, IV.length, out, 8*(i-1), 8);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < IV.length; i++) {
|
||||
if (IV[i] != buffer[i]) {
|
||||
throw new InvalidKeyException("Integrity check failed");
|
||||
}
|
||||
}
|
||||
return ConstructKeys.constructKey(out, wrappedKeyAlgorithm,
|
||||
wrappedKeyType);
|
||||
} finally {
|
||||
Arrays.fill(out, (byte)0);
|
||||
Arrays.fill(buffer, (byte)0);
|
||||
}
|
||||
return ConstructKeys.constructKey(out, wrappedKeyAlgorithm,
|
||||
wrappedKeyType);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2021, 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
|
||||
@ -27,6 +27,7 @@ package com.sun.crypto.provider;
|
||||
|
||||
import java.security.*;
|
||||
import java.security.spec.AlgorithmParameterSpec;
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.crypto.*;
|
||||
|
||||
@ -180,6 +181,9 @@ public final class ARCFOURCipher extends CipherSpi {
|
||||
|
||||
// init method. Check opmode and key, then call init(byte[]).
|
||||
private void init(int opmode, Key key) throws InvalidKeyException {
|
||||
if (lastKey != null) {
|
||||
Arrays.fill(lastKey, (byte)0);
|
||||
}
|
||||
if ((opmode < Cipher.ENCRYPT_MODE) || (opmode > Cipher.UNWRAP_MODE)) {
|
||||
throw new InvalidKeyException("Unknown opmode: " + opmode);
|
||||
}
|
||||
@ -199,6 +203,7 @@ public final class ARCFOURCipher extends CipherSpi {
|
||||
}
|
||||
byte[] encodedKey = key.getEncoded();
|
||||
if ((encodedKey.length < 5) || (encodedKey.length > 128)) {
|
||||
Arrays.fill(encodedKey, (byte)0);
|
||||
throw new InvalidKeyException
|
||||
("Key length must be between 40 and 1024 bit");
|
||||
}
|
||||
@ -244,19 +249,31 @@ public final class ARCFOURCipher extends CipherSpi {
|
||||
if ((encoded == null) || (encoded.length == 0)) {
|
||||
throw new InvalidKeyException("Could not obtain encoded key");
|
||||
}
|
||||
return engineDoFinal(encoded, 0, encoded.length);
|
||||
try {
|
||||
return engineDoFinal(encoded, 0, encoded.length);
|
||||
} finally {
|
||||
Arrays.fill(encoded, (byte)0);
|
||||
}
|
||||
}
|
||||
|
||||
// see JCE spec
|
||||
protected Key engineUnwrap(byte[] wrappedKey, String algorithm,
|
||||
int type) throws InvalidKeyException, NoSuchAlgorithmException {
|
||||
byte[] encoded = engineDoFinal(wrappedKey, 0, wrappedKey.length);
|
||||
return ConstructKeys.constructKey(encoded, algorithm, type);
|
||||
byte[] encoded = null;
|
||||
try {
|
||||
encoded = engineDoFinal(wrappedKey, 0, wrappedKey.length);
|
||||
return ConstructKeys.constructKey(encoded, algorithm, type);
|
||||
} finally {
|
||||
if (encoded != null) {
|
||||
Arrays.fill(encoded, (byte) 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// see JCE spec
|
||||
protected int engineGetKeySize(Key key) throws InvalidKeyException {
|
||||
byte[] encodedKey = getEncodedKey(key);
|
||||
Arrays.fill(encodedKey, (byte)0);
|
||||
return Math.multiplyExact(encodedKey.length, 8);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2021, 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
|
||||
@ -27,6 +27,8 @@ package com.sun.crypto.provider;
|
||||
|
||||
import java.security.*;
|
||||
import java.security.spec.*;
|
||||
import java.util.Arrays;
|
||||
|
||||
import sun.security.util.*;
|
||||
import javax.crypto.*;
|
||||
import javax.crypto.spec.*;
|
||||
@ -373,7 +375,9 @@ public final class BlowfishCipher extends CipherSpi {
|
||||
* @exception InvalidKeyException if <code>key</code> is invalid.
|
||||
*/
|
||||
protected int engineGetKeySize(Key key) throws InvalidKeyException {
|
||||
return Math.multiplyExact(key.getEncoded().length, 8);
|
||||
byte[] encodedKey = key.getEncoded();
|
||||
Arrays.fill(encodedKey, (byte)0);
|
||||
return Math.multiplyExact(encodedKey.length, 8);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2021, 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
|
||||
@ -29,6 +29,7 @@ import java.security.SecureRandom;
|
||||
import java.security.InvalidParameterException;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.spec.AlgorithmParameterSpec;
|
||||
import java.util.Arrays;
|
||||
import javax.crypto.KeyGeneratorSpi;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
@ -110,6 +111,10 @@ public final class BlowfishKeyGenerator extends KeyGeneratorSpi {
|
||||
byte[] keyBytes = new byte[this.keysize];
|
||||
this.random.nextBytes(keyBytes);
|
||||
|
||||
return new SecretKeySpec(keyBytes, "Blowfish");
|
||||
try {
|
||||
return new SecretKeySpec(keyBytes, "Blowfish");
|
||||
} finally {
|
||||
Arrays.fill(keyBytes, (byte)0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2021, 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
|
||||
@ -33,6 +33,7 @@ import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.security.*;
|
||||
import java.security.spec.AlgorithmParameterSpec;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import javax.crypto.*;
|
||||
import javax.crypto.spec.ChaCha20ParameterSpec;
|
||||
@ -546,6 +547,9 @@ abstract class ChaCha20Cipher extends CipherSpi {
|
||||
// assigning them to the object.
|
||||
byte[] newKeyBytes = getEncodedKey(key);
|
||||
checkKeyAndNonce(newKeyBytes, newNonce);
|
||||
if (this.keyBytes != null) {
|
||||
Arrays.fill(this.keyBytes, (byte)0);
|
||||
}
|
||||
this.keyBytes = newKeyBytes;
|
||||
nonce = newNonce;
|
||||
|
||||
@ -612,6 +616,9 @@ abstract class ChaCha20Cipher extends CipherSpi {
|
||||
}
|
||||
byte[] encodedKey = key.getEncoded();
|
||||
if (encodedKey == null || encodedKey.length != 32) {
|
||||
if (encodedKey != null) {
|
||||
Arrays.fill(encodedKey, (byte)0);
|
||||
}
|
||||
throw new InvalidKeyException("Key length must be 256 bits");
|
||||
}
|
||||
return encodedKey;
|
||||
@ -790,6 +797,7 @@ abstract class ChaCha20Cipher extends CipherSpi {
|
||||
@Override
|
||||
protected int engineGetKeySize(Key key) throws InvalidKeyException {
|
||||
byte[] encodedKey = getEncodedKey(key);
|
||||
Arrays.fill(encodedKey, (byte)0);
|
||||
return encodedKey.length << 3;
|
||||
}
|
||||
|
||||
|
@ -504,97 +504,106 @@ final class CipherCore {
|
||||
|| (opmode == Cipher.UNWRAP_MODE);
|
||||
|
||||
byte[] keyBytes = getKeyBytes(key);
|
||||
int tagLen = -1;
|
||||
byte[] ivBytes = null;
|
||||
if (params != null) {
|
||||
if (cipherMode == GCM_MODE) {
|
||||
if (params instanceof GCMParameterSpec) {
|
||||
tagLen = ((GCMParameterSpec)params).getTLen();
|
||||
if (tagLen < 96 || tagLen > 128 || ((tagLen & 0x07) != 0)) {
|
||||
try {
|
||||
int tagLen = -1;
|
||||
byte[] ivBytes = null;
|
||||
if (params != null) {
|
||||
if (cipherMode == GCM_MODE) {
|
||||
if (params instanceof GCMParameterSpec) {
|
||||
tagLen = ((GCMParameterSpec) params).getTLen();
|
||||
if (tagLen < 96 || tagLen > 128 || ((tagLen & 0x07) != 0)) {
|
||||
throw new InvalidAlgorithmParameterException
|
||||
("Unsupported TLen value; must be one of " +
|
||||
"{128, 120, 112, 104, 96}");
|
||||
}
|
||||
tagLen = tagLen >> 3;
|
||||
ivBytes = ((GCMParameterSpec) params).getIV();
|
||||
} else {
|
||||
throw new InvalidAlgorithmParameterException
|
||||
("Unsupported TLen value; must be one of " +
|
||||
"{128, 120, 112, 104, 96}");
|
||||
}
|
||||
tagLen = tagLen >> 3;
|
||||
ivBytes = ((GCMParameterSpec)params).getIV();
|
||||
} else {
|
||||
throw new InvalidAlgorithmParameterException
|
||||
("Unsupported parameter: " + params);
|
||||
}
|
||||
} else {
|
||||
if (params instanceof IvParameterSpec) {
|
||||
ivBytes = ((IvParameterSpec)params).getIV();
|
||||
if ((ivBytes == null) || (ivBytes.length != blockSize)) {
|
||||
throw new InvalidAlgorithmParameterException
|
||||
("Wrong IV length: must be " + blockSize +
|
||||
" bytes long");
|
||||
}
|
||||
} else if (params instanceof RC2ParameterSpec) {
|
||||
ivBytes = ((RC2ParameterSpec)params).getIV();
|
||||
if ((ivBytes != null) && (ivBytes.length != blockSize)) {
|
||||
throw new InvalidAlgorithmParameterException
|
||||
("Wrong IV length: must be " + blockSize +
|
||||
" bytes long");
|
||||
("Unsupported parameter: " + params);
|
||||
}
|
||||
} else {
|
||||
throw new InvalidAlgorithmParameterException
|
||||
("Unsupported parameter: " + params);
|
||||
if (params instanceof IvParameterSpec) {
|
||||
ivBytes = ((IvParameterSpec) params).getIV();
|
||||
if ((ivBytes == null) || (ivBytes.length != blockSize)) {
|
||||
throw new InvalidAlgorithmParameterException
|
||||
("Wrong IV length: must be " + blockSize +
|
||||
" bytes long");
|
||||
}
|
||||
} else if (params instanceof RC2ParameterSpec) {
|
||||
ivBytes = ((RC2ParameterSpec) params).getIV();
|
||||
if ((ivBytes != null) && (ivBytes.length != blockSize)) {
|
||||
throw new InvalidAlgorithmParameterException
|
||||
("Wrong IV length: must be " + blockSize +
|
||||
" bytes long");
|
||||
}
|
||||
} else {
|
||||
throw new InvalidAlgorithmParameterException
|
||||
("Unsupported parameter: " + params);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cipherMode == ECB_MODE) {
|
||||
if (ivBytes != null) {
|
||||
throw new InvalidAlgorithmParameterException
|
||||
("ECB mode cannot use IV");
|
||||
}
|
||||
} else if (ivBytes == null) {
|
||||
if (decrypting) {
|
||||
throw new InvalidAlgorithmParameterException("Parameters "
|
||||
+ "missing");
|
||||
if (cipherMode == ECB_MODE) {
|
||||
if (ivBytes != null) {
|
||||
throw new InvalidAlgorithmParameterException
|
||||
("ECB mode cannot use IV");
|
||||
}
|
||||
} else if (ivBytes == null) {
|
||||
if (decrypting) {
|
||||
throw new InvalidAlgorithmParameterException("Parameters "
|
||||
+ "missing");
|
||||
}
|
||||
|
||||
if (random == null) {
|
||||
random = SunJCE.getRandom();
|
||||
}
|
||||
if (cipherMode == GCM_MODE) {
|
||||
ivBytes = new byte[GaloisCounterMode.DEFAULT_IV_LEN];
|
||||
} else {
|
||||
ivBytes = new byte[blockSize];
|
||||
}
|
||||
random.nextBytes(ivBytes);
|
||||
}
|
||||
|
||||
if (random == null) {
|
||||
random = SunJCE.getRandom();
|
||||
}
|
||||
buffered = 0;
|
||||
diffBlocksize = blockSize;
|
||||
|
||||
String algorithm = key.getAlgorithm();
|
||||
|
||||
// GCM mode needs additional handling
|
||||
if (cipherMode == GCM_MODE) {
|
||||
ivBytes = new byte[GaloisCounterMode.DEFAULT_IV_LEN];
|
||||
} else {
|
||||
ivBytes = new byte[blockSize];
|
||||
}
|
||||
random.nextBytes(ivBytes);
|
||||
}
|
||||
|
||||
buffered = 0;
|
||||
diffBlocksize = blockSize;
|
||||
|
||||
String algorithm = key.getAlgorithm();
|
||||
|
||||
// GCM mode needs additional handling
|
||||
if (cipherMode == GCM_MODE) {
|
||||
if(tagLen == -1) {
|
||||
tagLen = GaloisCounterMode.DEFAULT_TAG_LEN;
|
||||
}
|
||||
if (decrypting) {
|
||||
minBytes = tagLen;
|
||||
} else {
|
||||
// check key+iv for encryption in GCM mode
|
||||
requireReinit =
|
||||
Arrays.equals(ivBytes, lastEncIv) &&
|
||||
MessageDigest.isEqual(keyBytes, lastEncKey);
|
||||
if (requireReinit) {
|
||||
throw new InvalidAlgorithmParameterException
|
||||
("Cannot reuse iv for GCM encryption");
|
||||
if (tagLen == -1) {
|
||||
tagLen = GaloisCounterMode.DEFAULT_TAG_LEN;
|
||||
}
|
||||
lastEncIv = ivBytes;
|
||||
lastEncKey = keyBytes;
|
||||
if (decrypting) {
|
||||
minBytes = tagLen;
|
||||
} else {
|
||||
// check key+iv for encryption in GCM mode
|
||||
requireReinit =
|
||||
Arrays.equals(ivBytes, lastEncIv) &&
|
||||
MessageDigest.isEqual(keyBytes, lastEncKey);
|
||||
if (requireReinit) {
|
||||
throw new InvalidAlgorithmParameterException
|
||||
("Cannot reuse iv for GCM encryption");
|
||||
}
|
||||
lastEncIv = ivBytes;
|
||||
if (lastEncKey != null) {
|
||||
Arrays.fill(lastEncKey, (byte) 0);
|
||||
}
|
||||
lastEncKey = keyBytes;
|
||||
}
|
||||
((GaloisCounterMode) cipher).init
|
||||
(decrypting, algorithm, keyBytes, ivBytes, tagLen);
|
||||
} else {
|
||||
cipher.init(decrypting, algorithm, keyBytes, ivBytes);
|
||||
}
|
||||
// skip checking key+iv from now on until after doFinal()
|
||||
requireReinit = false;
|
||||
} finally {
|
||||
if (lastEncKey != keyBytes) {
|
||||
Arrays.fill(keyBytes, (byte) 0);
|
||||
}
|
||||
((GaloisCounterMode) cipher).init
|
||||
(decrypting, algorithm, keyBytes, ivBytes, tagLen);
|
||||
} else {
|
||||
cipher.init(decrypting, algorithm, keyBytes, ivBytes);
|
||||
}
|
||||
// skip checking key+iv from now on until after doFinal()
|
||||
requireReinit = false;
|
||||
}
|
||||
|
||||
void init(int opmode, Key key, AlgorithmParameters params,
|
||||
@ -1156,7 +1165,11 @@ final class CipherCore {
|
||||
throw new InvalidKeyException("Cannot get an encoding of " +
|
||||
"the key to be wrapped");
|
||||
}
|
||||
result = doFinal(encodedKey, 0, encodedKey.length);
|
||||
try {
|
||||
result = doFinal(encodedKey, 0, encodedKey.length);
|
||||
} finally {
|
||||
Arrays.fill(encodedKey, (byte)0);
|
||||
}
|
||||
} catch (BadPaddingException e) {
|
||||
// Should never happen
|
||||
}
|
||||
@ -1197,8 +1210,12 @@ final class CipherCore {
|
||||
throw new InvalidKeyException("The wrapped key does not have " +
|
||||
"the correct length");
|
||||
}
|
||||
return ConstructKeys.constructKey(encodedKey, wrappedKeyAlgorithm,
|
||||
wrappedKeyType);
|
||||
try {
|
||||
return ConstructKeys.constructKey(encodedKey, wrappedKeyAlgorithm,
|
||||
wrappedKeyType);
|
||||
} finally {
|
||||
Arrays.fill(encodedKey, (byte)0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,259 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2013, 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.crypto.provider;
|
||||
|
||||
import java.security.Key;
|
||||
import java.security.PublicKey;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchProviderException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.CipherSpi;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
/**
|
||||
* This class entends the javax.crypto.CipherSpi class with a concrete
|
||||
* implementation of the methods for wrapping and unwrapping
|
||||
* keys.
|
||||
*
|
||||
* @author Sharon Liu
|
||||
*
|
||||
*
|
||||
* @see javax.crypto.CipherSpi
|
||||
* @see BlowfishCipher
|
||||
* @see DESCipher
|
||||
* @see PBEWithMD5AndDESCipher
|
||||
*/
|
||||
|
||||
public abstract class CipherWithWrappingSpi extends CipherSpi {
|
||||
|
||||
/**
|
||||
* Wrap a key.
|
||||
*
|
||||
* @param key the key to be wrapped.
|
||||
*
|
||||
* @return the wrapped key.
|
||||
*
|
||||
* @exception IllegalBlockSizeException if this cipher is a block
|
||||
* cipher, no padding has been requested, and the length of the
|
||||
* encoding of the key to be wrapped is not a
|
||||
* multiple of the block size.
|
||||
*
|
||||
* @exception InvalidKeyException if it is impossible or unsafe to
|
||||
* wrap the key with this cipher (e.g., a hardware protected key is
|
||||
* being passed to a software only cipher).
|
||||
*/
|
||||
protected final byte[] engineWrap(Key key)
|
||||
throws IllegalBlockSizeException, InvalidKeyException
|
||||
{
|
||||
byte[] result = null;
|
||||
|
||||
try {
|
||||
byte[] encodedKey = key.getEncoded();
|
||||
if ((encodedKey == null) || (encodedKey.length == 0)) {
|
||||
throw new InvalidKeyException("Cannot get an encoding of " +
|
||||
"the key to be wrapped");
|
||||
}
|
||||
|
||||
result = engineDoFinal(encodedKey, 0, encodedKey.length);
|
||||
} catch (BadPaddingException e) {
|
||||
// Should never happen
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unwrap a previously wrapped key.
|
||||
*
|
||||
* @param wrappedKey the key to be unwrapped.
|
||||
*
|
||||
* @param wrappedKeyAlgorithm the algorithm the wrapped key is for.
|
||||
*
|
||||
* @param wrappedKeyType the type of the wrapped key.
|
||||
* This is one of <code>Cipher.SECRET_KEY</code>,
|
||||
* <code>Cipher.PRIVATE_KEY</code>, or <code>Cipher.PUBLIC_KEY</code>.
|
||||
*
|
||||
* @return the unwrapped key.
|
||||
*
|
||||
* @exception InvalidKeyException if <code>wrappedKey</code> does not
|
||||
* represent a wrapped key, or if the algorithm associated with the
|
||||
* wrapped key is different from <code>wrappedKeyAlgorithm</code>
|
||||
* and/or its key type is different from <code>wrappedKeyType</code>.
|
||||
*
|
||||
* @exception NoSuchAlgorithmException if no installed providers
|
||||
* can create keys for the <code>wrappedKeyAlgorithm</code>.
|
||||
*/
|
||||
protected final Key engineUnwrap(byte[] wrappedKey,
|
||||
String wrappedKeyAlgorithm,
|
||||
int wrappedKeyType)
|
||||
throws InvalidKeyException, NoSuchAlgorithmException
|
||||
{
|
||||
byte[] encodedKey;
|
||||
Key result = null;
|
||||
|
||||
try {
|
||||
encodedKey = engineDoFinal(wrappedKey, 0,
|
||||
wrappedKey.length);
|
||||
} catch (BadPaddingException ePadding) {
|
||||
throw new InvalidKeyException();
|
||||
} catch (IllegalBlockSizeException eBlockSize) {
|
||||
throw new InvalidKeyException();
|
||||
}
|
||||
|
||||
switch (wrappedKeyType) {
|
||||
case Cipher.SECRET_KEY:
|
||||
result = constructSecretKey(encodedKey,
|
||||
wrappedKeyAlgorithm);
|
||||
break;
|
||||
case Cipher.PRIVATE_KEY:
|
||||
result = constructPrivateKey(encodedKey,
|
||||
wrappedKeyAlgorithm);
|
||||
break;
|
||||
case Cipher.PUBLIC_KEY:
|
||||
result = constructPublicKey(encodedKey,
|
||||
wrappedKeyAlgorithm);
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a public key from its encoding.
|
||||
*
|
||||
* @param encodedKey the encoding of a public key.
|
||||
*
|
||||
* @param encodedKeyAlgorithm the algorithm the encodedKey is for.
|
||||
*
|
||||
* @return a public key constructed from the encodedKey.
|
||||
*/
|
||||
private final PublicKey constructPublicKey(byte[] encodedKey,
|
||||
String encodedKeyAlgorithm)
|
||||
throws InvalidKeyException, NoSuchAlgorithmException
|
||||
{
|
||||
PublicKey key = null;
|
||||
|
||||
try {
|
||||
KeyFactory keyFactory =
|
||||
KeyFactory.getInstance(encodedKeyAlgorithm,
|
||||
SunJCE.getInstance());
|
||||
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encodedKey);
|
||||
key = keyFactory.generatePublic(keySpec);
|
||||
} catch (NoSuchAlgorithmException nsae) {
|
||||
// Try to see whether there is another
|
||||
// provider which supports this algorithm
|
||||
try {
|
||||
KeyFactory keyFactory =
|
||||
KeyFactory.getInstance(encodedKeyAlgorithm);
|
||||
X509EncodedKeySpec keySpec =
|
||||
new X509EncodedKeySpec(encodedKey);
|
||||
key = keyFactory.generatePublic(keySpec);
|
||||
} catch (NoSuchAlgorithmException nsae2) {
|
||||
throw new NoSuchAlgorithmException("No installed providers " +
|
||||
"can create keys for the " +
|
||||
encodedKeyAlgorithm +
|
||||
"algorithm");
|
||||
} catch (InvalidKeySpecException ikse2) {
|
||||
// Should never happen.
|
||||
}
|
||||
} catch (InvalidKeySpecException ikse) {
|
||||
// Should never happen.
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a private key from its encoding.
|
||||
*
|
||||
* @param encodedKey the encoding of a private key.
|
||||
*
|
||||
* @param encodedKeyAlgorithm the algorithm the wrapped key is for.
|
||||
*
|
||||
* @return a private key constructed from the encodedKey.
|
||||
*/
|
||||
private final PrivateKey constructPrivateKey(byte[] encodedKey,
|
||||
String encodedKeyAlgorithm)
|
||||
throws InvalidKeyException, NoSuchAlgorithmException
|
||||
{
|
||||
PrivateKey key = null;
|
||||
|
||||
try {
|
||||
KeyFactory keyFactory =
|
||||
KeyFactory.getInstance(encodedKeyAlgorithm,
|
||||
SunJCE.getInstance());
|
||||
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encodedKey);
|
||||
return keyFactory.generatePrivate(keySpec);
|
||||
} catch (NoSuchAlgorithmException nsae) {
|
||||
// Try to see whether there is another
|
||||
// provider which supports this algorithm
|
||||
try {
|
||||
KeyFactory keyFactory =
|
||||
KeyFactory.getInstance(encodedKeyAlgorithm);
|
||||
PKCS8EncodedKeySpec keySpec =
|
||||
new PKCS8EncodedKeySpec(encodedKey);
|
||||
key = keyFactory.generatePrivate(keySpec);
|
||||
} catch (NoSuchAlgorithmException nsae2) {
|
||||
throw new NoSuchAlgorithmException("No installed providers " +
|
||||
"can create keys for the " +
|
||||
encodedKeyAlgorithm +
|
||||
"algorithm");
|
||||
} catch (InvalidKeySpecException ikse2) {
|
||||
// Should never happen.
|
||||
}
|
||||
} catch (InvalidKeySpecException ikse) {
|
||||
// Should never happen.
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a secret key from its encoding.
|
||||
*
|
||||
* @param encodedKey the encoding of a secret key.
|
||||
*
|
||||
* @param encodedKeyAlgorithm the algorithm the secret key is for.
|
||||
*
|
||||
* @return a secret key constructed from the encodedKey.
|
||||
*/
|
||||
private final SecretKey constructSecretKey(byte[] encodedKey,
|
||||
String encodedKeyAlgorithm)
|
||||
{
|
||||
return (new SecretKeySpec(encodedKey, encodedKeyAlgorithm));
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2021, 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.security.Key;
|
||||
import java.security.PublicKey;
|
||||
import java.security.PrivateKey;
|
||||
@ -113,12 +115,11 @@ final class ConstructKeys {
|
||||
throws InvalidKeyException, NoSuchAlgorithmException
|
||||
{
|
||||
PrivateKey key = null;
|
||||
|
||||
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encodedKey);
|
||||
try {
|
||||
KeyFactory keyFactory =
|
||||
KeyFactory.getInstance(encodedKeyAlgorithm,
|
||||
SunJCE.getInstance());
|
||||
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encodedKey);
|
||||
return keyFactory.generatePrivate(keySpec);
|
||||
} catch (NoSuchAlgorithmException nsae) {
|
||||
// Try to see whether there is another
|
||||
@ -126,8 +127,6 @@ final class ConstructKeys {
|
||||
try {
|
||||
KeyFactory keyFactory =
|
||||
KeyFactory.getInstance(encodedKeyAlgorithm);
|
||||
PKCS8EncodedKeySpec keySpec =
|
||||
new PKCS8EncodedKeySpec(encodedKey);
|
||||
key = keyFactory.generatePrivate(keySpec);
|
||||
} catch (NoSuchAlgorithmException nsae2) {
|
||||
throw new NoSuchAlgorithmException("No installed providers " +
|
||||
@ -145,6 +144,8 @@ final class ConstructKeys {
|
||||
new InvalidKeyException("Cannot construct private key");
|
||||
ike.initCause(ikse);
|
||||
throw ike;
|
||||
} finally {
|
||||
SharedSecrets.getJavaSecuritySpecAccess().clearEncodedKeySpec(keySpec);
|
||||
}
|
||||
|
||||
return key;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2021, 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
|
||||
@ -27,6 +27,7 @@ package com.sun.crypto.provider;
|
||||
|
||||
import java.security.*;
|
||||
import java.security.spec.*;
|
||||
import java.util.Arrays;
|
||||
import javax.crypto.*;
|
||||
import javax.crypto.spec.*;
|
||||
import javax.crypto.BadPaddingException;
|
||||
@ -369,6 +370,7 @@ public final class DESCipher extends CipherSpi {
|
||||
*/
|
||||
protected int engineGetKeySize(Key key) throws InvalidKeyException {
|
||||
byte[] encoded = key.getEncoded();
|
||||
Arrays.fill(encoded, (byte)0);
|
||||
if (encoded.length != 8) {
|
||||
throw new InvalidKeyException("Invalid key length: " +
|
||||
encoded.length + " bytes");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2021, 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
|
||||
@ -158,6 +158,6 @@ final class DESKey implements SecretKey {
|
||||
return new KeyRep(KeyRep.Type.SECRET,
|
||||
getAlgorithm(),
|
||||
getFormat(),
|
||||
getEncoded());
|
||||
key);
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ import javax.crypto.spec.DESKeySpec;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.spec.KeySpec;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.util.Arrays;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
/**
|
||||
@ -63,17 +64,20 @@ public final class DESKeyFactory extends SecretKeyFactorySpi {
|
||||
throws InvalidKeySpecException {
|
||||
|
||||
try {
|
||||
byte[] encoded;
|
||||
if (keySpec instanceof DESKeySpec) {
|
||||
return new DESKey(((DESKeySpec)keySpec).getKey());
|
||||
encoded = ((DESKeySpec)keySpec).getKey();
|
||||
} else if (keySpec instanceof SecretKeySpec) {
|
||||
encoded = ((SecretKeySpec)keySpec).getEncoded();
|
||||
} else {
|
||||
throw new InvalidKeySpecException(
|
||||
"Inappropriate key specification");
|
||||
}
|
||||
|
||||
if (keySpec instanceof SecretKeySpec) {
|
||||
return new DESKey(((SecretKeySpec)keySpec).getEncoded());
|
||||
try {
|
||||
return new DESKey(encoded);
|
||||
} finally {
|
||||
Arrays.fill(encoded, (byte)0);
|
||||
}
|
||||
|
||||
throw new InvalidKeySpecException(
|
||||
"Inappropriate key specification");
|
||||
|
||||
} catch (InvalidKeyException e) {
|
||||
throw new InvalidKeySpecException(e.getMessage());
|
||||
}
|
||||
@ -106,9 +110,15 @@ public final class DESKeyFactory extends SecretKeyFactorySpi {
|
||||
|
||||
// Check if requested key spec is amongst the valid ones
|
||||
if ((keySpec != null) &&
|
||||
keySpec.isAssignableFrom(DESKeySpec.class)) {
|
||||
return new DESKeySpec(key.getEncoded());
|
||||
|
||||
keySpec.isAssignableFrom(DESKeySpec.class)) {
|
||||
byte[] encoded = key.getEncoded();
|
||||
try {
|
||||
return new DESKeySpec(encoded);
|
||||
} finally {
|
||||
if (encoded != null) {
|
||||
Arrays.fill(encoded, (byte) 0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new InvalidKeySpecException
|
||||
("Inappropriate key specification");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2021, 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
|
||||
@ -30,6 +30,7 @@ import java.security.InvalidParameterException;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.spec.AlgorithmParameterSpec;
|
||||
import java.util.Arrays;
|
||||
import javax.crypto.KeyGeneratorSpi;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.DESKeySpec;
|
||||
@ -112,6 +113,7 @@ public final class DESKeyGenerator extends KeyGeneratorSpi {
|
||||
setParityBit(key, 0);
|
||||
} while (DESKeySpec.isWeak(key, 0));
|
||||
desKey = new DESKey(key);
|
||||
Arrays.fill(key, (byte)0);
|
||||
} catch (InvalidKeyException e) {
|
||||
// this is never thrown
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2021, 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
|
||||
@ -27,6 +27,7 @@ package com.sun.crypto.provider;
|
||||
|
||||
import java.security.*;
|
||||
import java.security.spec.*;
|
||||
import java.util.Arrays;
|
||||
import javax.crypto.*;
|
||||
import javax.crypto.spec.*;
|
||||
|
||||
@ -366,6 +367,7 @@ public final class DESedeCipher extends CipherSpi {
|
||||
*/
|
||||
protected int engineGetKeySize(Key key) throws InvalidKeyException {
|
||||
byte[] encoded = key.getEncoded();
|
||||
Arrays.fill(encoded, (byte)0);
|
||||
if (encoded.length != 24) {
|
||||
throw new InvalidKeyException("Invalid key length: " +
|
||||
encoded.length + " bytes");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2021, 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
|
||||
@ -156,8 +156,8 @@ final class DESedeKey implements SecretKey {
|
||||
@java.io.Serial
|
||||
private Object writeReplace() throws java.io.ObjectStreamException {
|
||||
return new KeyRep(KeyRep.Type.SECRET,
|
||||
getAlgorithm(),
|
||||
getFormat(),
|
||||
getEncoded());
|
||||
getAlgorithm(),
|
||||
getFormat(),
|
||||
key);
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ import javax.crypto.spec.DESedeKeySpec;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.spec.KeySpec;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.util.Arrays;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
/**
|
||||
@ -63,15 +64,20 @@ public final class DESedeKeyFactory extends SecretKeyFactorySpi {
|
||||
throws InvalidKeySpecException {
|
||||
|
||||
try {
|
||||
byte[] encoded;
|
||||
if (keySpec instanceof DESedeKeySpec) {
|
||||
return new DESedeKey(((DESedeKeySpec)keySpec).getKey());
|
||||
encoded = ((DESedeKeySpec)keySpec).getKey();
|
||||
} else if (keySpec instanceof SecretKeySpec) {
|
||||
encoded = ((SecretKeySpec)keySpec).getEncoded();
|
||||
} else {
|
||||
throw new InvalidKeySpecException
|
||||
("Inappropriate key specification");
|
||||
}
|
||||
if (keySpec instanceof SecretKeySpec) {
|
||||
return new DESedeKey(((SecretKeySpec)keySpec).getEncoded());
|
||||
|
||||
try {
|
||||
return new DESedeKey(encoded);
|
||||
} finally {
|
||||
Arrays.fill(encoded, (byte)0);
|
||||
}
|
||||
throw new InvalidKeySpecException
|
||||
("Inappropriate key specification");
|
||||
} catch (InvalidKeyException e) {
|
||||
throw new InvalidKeySpecException(e.getMessage());
|
||||
}
|
||||
@ -103,8 +109,14 @@ public final class DESedeKeyFactory extends SecretKeyFactorySpi {
|
||||
|
||||
// Check if requested key spec is amongst the valid ones
|
||||
if (keySpec.isAssignableFrom(DESedeKeySpec.class)) {
|
||||
return new DESedeKeySpec(key.getEncoded());
|
||||
|
||||
byte[] encoded = key.getEncoded();
|
||||
try {
|
||||
return new DESedeKeySpec(encoded);
|
||||
} finally {
|
||||
if (encoded != null) {
|
||||
Arrays.fill(encoded, (byte) 0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new InvalidKeySpecException
|
||||
("Inappropriate key specification");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2004, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2004, 2021, 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
|
||||
@ -27,6 +27,7 @@ package com.sun.crypto.provider;
|
||||
|
||||
import java.security.*;
|
||||
import java.security.spec.*;
|
||||
import java.util.Arrays;
|
||||
import javax.crypto.*;
|
||||
import javax.crypto.spec.*;
|
||||
|
||||
@ -241,8 +242,14 @@ public final class DESedeWrapCipher extends CipherSpi {
|
||||
throw new UnsupportedOperationException("This cipher can " +
|
||||
"only be used for key wrapping and unwrapping");
|
||||
}
|
||||
cipher.init(decrypting, key.getAlgorithm(), key.getEncoded(),
|
||||
currIv);
|
||||
byte[] encoded = key.getEncoded();
|
||||
try {
|
||||
cipher.init(decrypting, key.getAlgorithm(), encoded, currIv);
|
||||
} finally {
|
||||
if (encoded != null) {
|
||||
Arrays.fill(encoded, (byte) 0);
|
||||
}
|
||||
}
|
||||
cipherKey = key;
|
||||
}
|
||||
|
||||
@ -416,6 +423,7 @@ public final class DESedeWrapCipher extends CipherSpi {
|
||||
*/
|
||||
protected int engineGetKeySize(Key key) throws InvalidKeyException {
|
||||
byte[] encoded = key.getEncoded();
|
||||
Arrays.fill(encoded, (byte)0);
|
||||
if (encoded.length != 24) {
|
||||
throw new InvalidKeyException("Invalid key length: " +
|
||||
encoded.length + " bytes");
|
||||
@ -448,47 +456,57 @@ public final class DESedeWrapCipher extends CipherSpi {
|
||||
"the key to be wrapped");
|
||||
}
|
||||
|
||||
byte[] cks = getChecksum(keyVal);
|
||||
byte[] in = new byte[Math.addExact(keyVal.length, CHECKSUM_LEN)];
|
||||
System.arraycopy(keyVal, 0, in, 0, keyVal.length);
|
||||
System.arraycopy(cks, 0, in, keyVal.length, CHECKSUM_LEN);
|
||||
|
||||
byte[] cipherKeyEncoded = cipherKey.getEncoded();
|
||||
byte[] out = new byte[Math.addExact(iv.length, in.length)];
|
||||
System.arraycopy(iv, 0, out, 0, iv.length);
|
||||
|
||||
cipher.encrypt(in, 0, in.length, out, iv.length);
|
||||
|
||||
// reverse the array content
|
||||
for (int i = 0; i < out.length/2; i++) {
|
||||
byte temp = out[i];
|
||||
out[i] = out[out.length-1-i];
|
||||
out[out.length-1-i] = temp;
|
||||
}
|
||||
try {
|
||||
cipher.init(false, cipherKey.getAlgorithm(),
|
||||
cipherKey.getEncoded(), IV2);
|
||||
} catch (InvalidKeyException ike) {
|
||||
// should never happen
|
||||
throw new RuntimeException("Internal cipher key is corrupted");
|
||||
} catch (InvalidAlgorithmParameterException iape) {
|
||||
// should never happen
|
||||
throw new RuntimeException("Internal cipher IV is invalid");
|
||||
}
|
||||
byte[] out2 = new byte[out.length];
|
||||
cipher.encrypt(out, 0, out.length, out2, 0);
|
||||
byte[] cks = getChecksum(keyVal);
|
||||
System.arraycopy(keyVal, 0, in, 0, keyVal.length);
|
||||
System.arraycopy(cks, 0, in, keyVal.length, CHECKSUM_LEN);
|
||||
|
||||
// restore cipher state to prior to this call
|
||||
try {
|
||||
cipher.init(decrypting, cipherKey.getAlgorithm(),
|
||||
cipherKey.getEncoded(), iv);
|
||||
} catch (InvalidKeyException ike) {
|
||||
// should never happen
|
||||
throw new RuntimeException("Internal cipher key is corrupted");
|
||||
} catch (InvalidAlgorithmParameterException iape) {
|
||||
// should never happen
|
||||
throw new RuntimeException("Internal cipher IV is invalid");
|
||||
System.arraycopy(iv, 0, out, 0, iv.length);
|
||||
|
||||
cipher.encrypt(in, 0, in.length, out, iv.length);
|
||||
|
||||
// reverse the array content
|
||||
for (int i = 0; i < out.length / 2; i++) {
|
||||
byte temp = out[i];
|
||||
out[i] = out[out.length - 1 - i];
|
||||
out[out.length - 1 - i] = temp;
|
||||
}
|
||||
try {
|
||||
cipher.init(false, cipherKey.getAlgorithm(),
|
||||
cipherKeyEncoded, IV2);
|
||||
} catch (InvalidKeyException ike) {
|
||||
// should never happen
|
||||
throw new RuntimeException("Internal cipher key is corrupted");
|
||||
} catch (InvalidAlgorithmParameterException iape) {
|
||||
// should never happen
|
||||
throw new RuntimeException("Internal cipher IV is invalid");
|
||||
}
|
||||
byte[] out2 = new byte[out.length];
|
||||
cipher.encrypt(out, 0, out.length, out2, 0);
|
||||
|
||||
// restore cipher state to prior to this call
|
||||
try {
|
||||
cipher.init(decrypting, cipherKey.getAlgorithm(),
|
||||
cipherKeyEncoded, iv);
|
||||
} catch (InvalidKeyException ike) {
|
||||
// should never happen
|
||||
throw new RuntimeException("Internal cipher key is corrupted");
|
||||
} catch (InvalidAlgorithmParameterException iape) {
|
||||
// should never happen
|
||||
throw new RuntimeException("Internal cipher IV is invalid");
|
||||
}
|
||||
return out2;
|
||||
} finally {
|
||||
Arrays.fill(keyVal, (byte)0);
|
||||
Arrays.fill(in, (byte)0);
|
||||
Arrays.fill(out, (byte)0);
|
||||
if (cipherKeyEncoded != null) {
|
||||
Arrays.fill(cipherKeyEncoded, (byte) 0);
|
||||
}
|
||||
}
|
||||
return out2;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -530,34 +548,46 @@ public final class DESedeWrapCipher extends CipherSpi {
|
||||
}
|
||||
iv = new byte[IV_LEN];
|
||||
System.arraycopy(buffer, 0, iv, 0, iv.length);
|
||||
try {
|
||||
cipher.init(true, cipherKey.getAlgorithm(), cipherKey.getEncoded(),
|
||||
iv);
|
||||
} catch (InvalidAlgorithmParameterException iape) {
|
||||
throw new InvalidKeyException("IV in wrapped key is invalid");
|
||||
}
|
||||
byte[] cipherKeyEncoded = cipherKey.getEncoded();
|
||||
byte[] out = null;
|
||||
byte[] buffer2 = new byte[buffer.length - iv.length];
|
||||
cipher.decrypt(buffer, iv.length, buffer2.length,
|
||||
buffer2, 0);
|
||||
int keyValLen = buffer2.length - CHECKSUM_LEN;
|
||||
byte[] cks = getChecksum(buffer2, 0, keyValLen);
|
||||
int offset = keyValLen;
|
||||
for (int i = 0; i < CHECKSUM_LEN; i++) {
|
||||
if (buffer2[offset + i] != cks[i]) {
|
||||
throw new InvalidKeyException("Checksum comparison failed");
|
||||
}
|
||||
}
|
||||
// restore cipher state to prior to this call
|
||||
try {
|
||||
cipher.init(decrypting, cipherKey.getAlgorithm(),
|
||||
cipherKey.getEncoded(), IV2);
|
||||
} catch (InvalidAlgorithmParameterException iape) {
|
||||
throw new InvalidKeyException("IV in wrapped key is invalid");
|
||||
try {
|
||||
cipher.init(true, cipherKey.getAlgorithm(), cipherKeyEncoded,
|
||||
iv);
|
||||
} catch (InvalidAlgorithmParameterException iape) {
|
||||
throw new InvalidKeyException("IV in wrapped key is invalid");
|
||||
}
|
||||
cipher.decrypt(buffer, iv.length, buffer2.length,
|
||||
buffer2, 0);
|
||||
int keyValLen = buffer2.length - CHECKSUM_LEN;
|
||||
byte[] cks = getChecksum(buffer2, 0, keyValLen);
|
||||
int offset = keyValLen;
|
||||
for (int i = 0; i < CHECKSUM_LEN; i++) {
|
||||
if (buffer2[offset + i] != cks[i]) {
|
||||
throw new InvalidKeyException("Checksum comparison failed");
|
||||
}
|
||||
}
|
||||
// restore cipher state to prior to this call
|
||||
try {
|
||||
cipher.init(decrypting, cipherKey.getAlgorithm(),
|
||||
cipherKeyEncoded, IV2);
|
||||
} catch (InvalidAlgorithmParameterException iape) {
|
||||
throw new InvalidKeyException("IV in wrapped key is invalid");
|
||||
}
|
||||
out = new byte[keyValLen];
|
||||
System.arraycopy(buffer2, 0, out, 0, keyValLen);
|
||||
return ConstructKeys.constructKey(out, wrappedKeyAlgorithm,
|
||||
wrappedKeyType);
|
||||
} finally {
|
||||
if (out != null) {
|
||||
Arrays.fill(out, (byte)0);
|
||||
}
|
||||
if (cipherKeyEncoded != null) {
|
||||
Arrays.fill(cipherKeyEncoded, (byte) 0);
|
||||
}
|
||||
Arrays.fill(buffer2, (byte)0);
|
||||
}
|
||||
byte[] out = new byte[keyValLen];
|
||||
System.arraycopy(buffer2, 0, out, 0, keyValLen);
|
||||
return ConstructKeys.constructKey(out, wrappedKeyAlgorithm,
|
||||
wrappedKeyType);
|
||||
}
|
||||
|
||||
private static final byte[] getChecksum(byte[] in) {
|
||||
@ -573,6 +603,7 @@ public final class DESedeWrapCipher extends CipherSpi {
|
||||
md.update(in, offset, len);
|
||||
byte[] cks = new byte[CHECKSUM_LEN];
|
||||
System.arraycopy(md.digest(), 0, cks, 0, cks.length);
|
||||
md.reset();
|
||||
return cks;
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ import java.security.spec.KeySpec;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
import java.util.Arrays;
|
||||
import javax.crypto.spec.DHPublicKeySpec;
|
||||
import javax.crypto.spec.DHPrivateKeySpec;
|
||||
import javax.crypto.spec.DHParameterSpec;
|
||||
@ -99,8 +100,7 @@ public final class DHKeyFactory extends KeyFactorySpi {
|
||||
* is inappropriate for this key factory to produce a private key.
|
||||
*/
|
||||
protected PrivateKey engineGeneratePrivate(KeySpec keySpec)
|
||||
throws InvalidKeySpecException
|
||||
{
|
||||
throws InvalidKeySpecException {
|
||||
try {
|
||||
if (keySpec instanceof DHPrivateKeySpec) {
|
||||
DHPrivateKeySpec dhPrivKeySpec = (DHPrivateKeySpec)keySpec;
|
||||
@ -109,9 +109,12 @@ public final class DHKeyFactory extends KeyFactorySpi {
|
||||
dhPrivKeySpec.getG());
|
||||
|
||||
} else if (keySpec instanceof PKCS8EncodedKeySpec) {
|
||||
return new DHPrivateKey
|
||||
(((PKCS8EncodedKeySpec)keySpec).getEncoded());
|
||||
|
||||
byte[] encoded = ((PKCS8EncodedKeySpec)keySpec).getEncoded();
|
||||
try {
|
||||
return new DHPrivateKey(encoded);
|
||||
} finally {
|
||||
Arrays.fill(encoded, (byte)0);
|
||||
}
|
||||
} else {
|
||||
throw new InvalidKeySpecException
|
||||
("Inappropriate key specification");
|
||||
@ -172,8 +175,12 @@ public final class DHKeyFactory extends KeyFactorySpi {
|
||||
params.getG()));
|
||||
|
||||
} else if (keySpec.isAssignableFrom(PKCS8EncodedKeySpec.class)) {
|
||||
return keySpec.cast(new PKCS8EncodedKeySpec(key.getEncoded()));
|
||||
|
||||
byte[] encoded = key.getEncoded();
|
||||
try {
|
||||
return keySpec.cast(new PKCS8EncodedKeySpec(encoded));
|
||||
} finally {
|
||||
Arrays.fill(encoded, (byte)0);
|
||||
}
|
||||
} else {
|
||||
throw new InvalidKeySpecException
|
||||
("Inappropriate key specification");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2021, 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,6 +26,7 @@
|
||||
package com.sun.crypto.provider;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import java.math.BigInteger;
|
||||
import java.security.KeyRep;
|
||||
@ -46,7 +47,7 @@ import sun.security.util.*;
|
||||
* @see java.security.KeyAgreement
|
||||
*/
|
||||
final class DHPrivateKey implements PrivateKey,
|
||||
javax.crypto.interfaces.DHPrivateKey, Serializable {
|
||||
javax.crypto.interfaces.DHPrivateKey, Serializable {
|
||||
|
||||
@java.io.Serial
|
||||
static final long serialVersionUID = 7565477590005668886L;
|
||||
@ -105,9 +106,12 @@ javax.crypto.interfaces.DHPrivateKey, Serializable {
|
||||
this.g = g;
|
||||
this.l = l;
|
||||
try {
|
||||
this.key = new DerValue(DerValue.tag_Integer,
|
||||
this.x.toByteArray()).toByteArray();
|
||||
this.encodedKey = getEncoded();
|
||||
byte[] xbytes = x.toByteArray();
|
||||
DerValue val = new DerValue(DerValue.tag_Integer, xbytes);
|
||||
this.key = val.toByteArray();
|
||||
val.clear();
|
||||
Arrays.fill(xbytes, (byte)0);
|
||||
encode();
|
||||
} catch (IOException e) {
|
||||
throw new ProviderException("Cannot produce ASN.1 encoding", e);
|
||||
}
|
||||
@ -122,9 +126,9 @@ javax.crypto.interfaces.DHPrivateKey, Serializable {
|
||||
* a Diffie-Hellman private key
|
||||
*/
|
||||
DHPrivateKey(byte[] encodedKey) throws InvalidKeyException {
|
||||
InputStream inStream = new ByteArrayInputStream(encodedKey);
|
||||
DerValue val = null;
|
||||
try {
|
||||
DerValue val = new DerValue(inStream);
|
||||
val = new DerValue(encodedKey);
|
||||
if (val.tag != DerValue.tag_Sequence) {
|
||||
throw new InvalidKeyException ("Key not a SEQUENCE");
|
||||
}
|
||||
@ -182,6 +186,10 @@ javax.crypto.interfaces.DHPrivateKey, Serializable {
|
||||
this.encodedKey = encodedKey.clone();
|
||||
} catch (IOException | NumberFormatException e) {
|
||||
throw new InvalidKeyException("Error parsing key encoding", e);
|
||||
} finally {
|
||||
if (val != null) {
|
||||
val.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -203,6 +211,15 @@ javax.crypto.interfaces.DHPrivateKey, Serializable {
|
||||
* Get the encoding of the key.
|
||||
*/
|
||||
public synchronized byte[] getEncoded() {
|
||||
encode();
|
||||
return encodedKey.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the encodedKey field if it has not been calculated.
|
||||
* Could generate null.
|
||||
*/
|
||||
private void encode() {
|
||||
if (this.encodedKey == null) {
|
||||
try {
|
||||
DerOutputStream tmp = new DerOutputStream();
|
||||
@ -238,14 +255,13 @@ javax.crypto.interfaces.DHPrivateKey, Serializable {
|
||||
tmp.putOctetString(this.key);
|
||||
|
||||
// make it a SEQUENCE
|
||||
DerOutputStream derKey = new DerOutputStream();
|
||||
derKey.write(DerValue.tag_Sequence, tmp);
|
||||
this.encodedKey = derKey.toByteArray();
|
||||
DerValue val = DerValue.wrap(DerValue.tag_Sequence, tmp);
|
||||
this.encodedKey = val.toByteArray();
|
||||
val.clear();
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
return this.encodedKey.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -314,9 +330,10 @@ javax.crypto.interfaces.DHPrivateKey, Serializable {
|
||||
*/
|
||||
@java.io.Serial
|
||||
private Object writeReplace() throws java.io.ObjectStreamException {
|
||||
encode();
|
||||
return new KeyRep(KeyRep.Type.PRIVATE,
|
||||
getAlgorithm(),
|
||||
getFormat(),
|
||||
getEncoded());
|
||||
getAlgorithm(),
|
||||
getFormat(),
|
||||
encodedKey);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2021, 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
|
||||
@ -29,6 +29,7 @@ import java.security.SecureRandom;
|
||||
import java.security.InvalidParameterException;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.spec.AlgorithmParameterSpec;
|
||||
import java.util.Arrays;
|
||||
import javax.crypto.KeyGeneratorSpi;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
@ -104,6 +105,10 @@ public final class HmacMD5KeyGenerator extends KeyGeneratorSpi {
|
||||
byte[] keyBytes = new byte[this.keysize];
|
||||
this.random.nextBytes(keyBytes);
|
||||
|
||||
return new SecretKeySpec(keyBytes, "HmacMD5");
|
||||
try {
|
||||
return new SecretKeySpec(keyBytes, "HmacMD5");
|
||||
} finally {
|
||||
Arrays.fill(keyBytes, (byte)0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2021, 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
|
||||
@ -29,6 +29,7 @@ import java.security.SecureRandom;
|
||||
import java.security.InvalidParameterException;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.spec.AlgorithmParameterSpec;
|
||||
import java.util.Arrays;
|
||||
import javax.crypto.KeyGeneratorSpi;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
@ -103,7 +104,10 @@ public final class HmacSHA1KeyGenerator extends KeyGeneratorSpi {
|
||||
|
||||
byte[] keyBytes = new byte[this.keysize];
|
||||
this.random.nextBytes(keyBytes);
|
||||
|
||||
return new SecretKeySpec(keyBytes, "HmacSHA1");
|
||||
try {
|
||||
return new SecretKeySpec(keyBytes, "HmacSHA1");
|
||||
} finally {
|
||||
Arrays.fill(keyBytes, (byte)0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2021, 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
|
||||
@ -27,6 +27,7 @@ package com.sun.crypto.provider;
|
||||
|
||||
import java.security.*;
|
||||
import java.security.spec.AlgorithmParameterSpec;
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.crypto.*;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
@ -102,7 +103,11 @@ final class KeyGeneratorCore {
|
||||
}
|
||||
byte[] b = new byte[(keySize + 7) >> 3];
|
||||
random.nextBytes(b);
|
||||
return new SecretKeySpec(b, name);
|
||||
try {
|
||||
return new SecretKeySpec(b, name);
|
||||
} finally {
|
||||
Arrays.fill(b, (byte)0);
|
||||
}
|
||||
}
|
||||
|
||||
// nested static classes for the Hmac key generator
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2021, 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
|
||||
@ -46,6 +46,7 @@ import javax.crypto.SealedObject;
|
||||
import javax.crypto.spec.*;
|
||||
import javax.security.auth.DestroyFailedException;
|
||||
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
import sun.security.x509.AlgorithmId;
|
||||
import sun.security.util.ObjectIdentifier;
|
||||
import sun.security.util.KnownOIDs;
|
||||
@ -201,10 +202,17 @@ final class KeyProtector {
|
||||
|
||||
// determine the private-key algorithm, and parse private key
|
||||
// using the appropriate key factory
|
||||
PrivateKeyInfo privateKeyInfo = new PrivateKeyInfo(plain);
|
||||
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(plain);
|
||||
String oidName = new AlgorithmId
|
||||
(new PrivateKeyInfo(plain).getAlgorithm().getOID()).getName();
|
||||
KeyFactory kFac = KeyFactory.getInstance(oidName);
|
||||
return kFac.generatePrivate(new PKCS8EncodedKeySpec(plain));
|
||||
(privateKeyInfo.getAlgorithm().getOID()).getName();
|
||||
try {
|
||||
KeyFactory kFac = KeyFactory.getInstance(oidName);
|
||||
return kFac.generatePrivate(spec);
|
||||
} finally {
|
||||
privateKeyInfo.clear();
|
||||
SharedSecrets.getJavaSecuritySpecAccess().clearEncodedKeySpec(spec);
|
||||
}
|
||||
} catch (NoSuchAlgorithmException ex) {
|
||||
// Note: this catch needed to be here because of the
|
||||
// later catch of GeneralSecurityException
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2021, 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
|
||||
@ -167,8 +167,8 @@ final class PBEKey implements SecretKey {
|
||||
@java.io.Serial
|
||||
private Object writeReplace() throws java.io.ObjectStreamException {
|
||||
return new KeyRep(KeyRep.Type.SECRET,
|
||||
getAlgorithm(),
|
||||
getFormat(),
|
||||
getEncoded());
|
||||
getAlgorithm(),
|
||||
getFormat(),
|
||||
key);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2021, 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
|
||||
@ -292,8 +292,12 @@ abstract class PBEKeyFactory extends SecretKeyFactorySpi {
|
||||
PBEKeySpec pbeKeySpec = (PBEKeySpec)engineGetKeySpec
|
||||
(key, PBEKeySpec.class);
|
||||
|
||||
// Create key from spec, and return it
|
||||
return engineGenerateSecret(pbeKeySpec);
|
||||
try {
|
||||
// Create key from spec, and return it
|
||||
return engineGenerateSecret(pbeKeySpec);
|
||||
} finally {
|
||||
pbeKeySpec.clearPassword();
|
||||
}
|
||||
} else {
|
||||
throw new InvalidKeyException("Invalid key format/algorithm");
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2021, 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
|
||||
@ -537,9 +537,14 @@ final class PBES1Core {
|
||||
String wrappedKeyAlgorithm,
|
||||
int wrappedKeyType)
|
||||
throws InvalidKeyException, NoSuchAlgorithmException {
|
||||
byte[] encodedKey;
|
||||
try {
|
||||
encodedKey = doFinal(wrappedKey, 0, wrappedKey.length);
|
||||
byte[] encodedKey = doFinal(wrappedKey, 0, wrappedKey.length);
|
||||
try {
|
||||
return ConstructKeys.constructKey(encodedKey, wrappedKeyAlgorithm,
|
||||
wrappedKeyType);
|
||||
} finally {
|
||||
Arrays.fill(encodedKey, (byte)0);
|
||||
}
|
||||
} catch (BadPaddingException ePadding) {
|
||||
throw new InvalidKeyException("The wrapped key is not padded " +
|
||||
"correctly");
|
||||
@ -547,7 +552,5 @@ final class PBES1Core {
|
||||
throw new InvalidKeyException("The wrapped key does not have " +
|
||||
"the correct length");
|
||||
}
|
||||
return ConstructKeys.constructKey(encodedKey, wrappedKeyAlgorithm,
|
||||
wrappedKeyType);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2021, 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
|
||||
@ -274,18 +274,20 @@ abstract class PBES2Core extends CipherSpi {
|
||||
if (passwdBytes != null) Arrays.fill(passwdBytes, (byte)0x00);
|
||||
}
|
||||
|
||||
SecretKey s = null;
|
||||
PBKDF2KeyImpl s;
|
||||
|
||||
try {
|
||||
s = kdf.engineGenerateSecret(pbeSpec);
|
||||
|
||||
s = (PBKDF2KeyImpl)kdf.engineGenerateSecret(pbeSpec);
|
||||
} catch (InvalidKeySpecException ikse) {
|
||||
InvalidKeyException ike =
|
||||
new InvalidKeyException("Cannot construct PBE key");
|
||||
ike.initCause(ikse);
|
||||
throw ike;
|
||||
} finally {
|
||||
pbeSpec.clearPassword();
|
||||
}
|
||||
byte[] derivedKey = s.getEncoded();
|
||||
s.clearPassword();
|
||||
SecretKeySpec cipherKey = new SecretKeySpec(derivedKey, cipherAlgo);
|
||||
|
||||
// initialize the underlying cipher
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2021, 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
|
||||
@ -28,6 +28,7 @@ package com.sun.crypto.provider;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.spec.KeySpec;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.util.Arrays;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.SecretKeyFactorySpi;
|
||||
import javax.crypto.spec.PBEKeySpec;
|
||||
@ -94,9 +95,17 @@ abstract class PBKDF2Core extends SecretKeyFactorySpi {
|
||||
&& PBEKeySpec.class.isAssignableFrom(keySpecCl)) {
|
||||
javax.crypto.interfaces.PBEKey pKey =
|
||||
(javax.crypto.interfaces.PBEKey) key;
|
||||
return new PBEKeySpec
|
||||
(pKey.getPassword(), pKey.getSalt(),
|
||||
pKey.getIterationCount(), pKey.getEncoded().length*8);
|
||||
char[] passwd = pKey.getPassword();
|
||||
byte[] encoded = pKey.getEncoded();
|
||||
try {
|
||||
return new PBEKeySpec(passwd, pKey.getSalt(),
|
||||
pKey.getIterationCount(), encoded.length * 8);
|
||||
} finally {
|
||||
if (passwd != null) {
|
||||
Arrays.fill(passwd, (char) 0);
|
||||
}
|
||||
Arrays.fill(encoded, (byte)0);
|
||||
}
|
||||
} else {
|
||||
throw new InvalidKeySpecException("Invalid key spec");
|
||||
}
|
||||
@ -132,18 +141,26 @@ abstract class PBKDF2Core extends SecretKeyFactorySpi {
|
||||
if (key instanceof javax.crypto.interfaces.PBEKey) {
|
||||
javax.crypto.interfaces.PBEKey pKey =
|
||||
(javax.crypto.interfaces.PBEKey) key;
|
||||
char[] password = pKey.getPassword();
|
||||
byte[] encoding = pKey.getEncoded();
|
||||
PBEKeySpec spec =
|
||||
new PBEKeySpec(password,
|
||||
pKey.getSalt(),
|
||||
pKey.getIterationCount(),
|
||||
encoding.length*8);
|
||||
try {
|
||||
PBEKeySpec spec =
|
||||
new PBEKeySpec(pKey.getPassword(),
|
||||
pKey.getSalt(),
|
||||
pKey.getIterationCount(),
|
||||
pKey.getEncoded().length*8);
|
||||
return new PBKDF2KeyImpl(spec, prfAlgo);
|
||||
} catch (InvalidKeySpecException re) {
|
||||
InvalidKeyException ike = new InvalidKeyException
|
||||
("Invalid key component(s)");
|
||||
ike.initCause(re);
|
||||
throw ike;
|
||||
} finally {
|
||||
if (password != null) {
|
||||
Arrays.fill(password, (char) 0);
|
||||
spec.clearPassword();
|
||||
}
|
||||
Arrays.fill(encoding, (byte)0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2021, 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
|
||||
@ -28,6 +28,7 @@ package com.sun.crypto.provider;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.spec.KeySpec;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.util.Arrays;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.SecretKeyFactorySpi;
|
||||
import javax.crypto.spec.PBEKeySpec;
|
||||
@ -94,9 +95,17 @@ public final class PBKDF2HmacSHA1Factory extends SecretKeyFactorySpi {
|
||||
&& PBEKeySpec.class.isAssignableFrom(keySpecCl)) {
|
||||
javax.crypto.interfaces.PBEKey pKey =
|
||||
(javax.crypto.interfaces.PBEKey) key;
|
||||
return new PBEKeySpec
|
||||
(pKey.getPassword(), pKey.getSalt(),
|
||||
pKey.getIterationCount(), pKey.getEncoded().length*8);
|
||||
char[] passwd = pKey.getPassword();
|
||||
byte[] encoded = pKey.getEncoded();
|
||||
try {
|
||||
return new PBEKeySpec(passwd, pKey.getSalt(),
|
||||
pKey.getIterationCount(), encoded.length * 8);
|
||||
} finally {
|
||||
if (passwd != null) {
|
||||
Arrays.fill(passwd, (char) 0);
|
||||
}
|
||||
Arrays.fill(encoded, (byte)0);
|
||||
}
|
||||
} else {
|
||||
throw new InvalidKeySpecException("Invalid key spec");
|
||||
}
|
||||
@ -132,18 +141,26 @@ public final class PBKDF2HmacSHA1Factory extends SecretKeyFactorySpi {
|
||||
if (key instanceof javax.crypto.interfaces.PBEKey) {
|
||||
javax.crypto.interfaces.PBEKey pKey =
|
||||
(javax.crypto.interfaces.PBEKey) key;
|
||||
char[] password = pKey.getPassword();
|
||||
byte[] encoding = pKey.getEncoded();
|
||||
PBEKeySpec spec =
|
||||
new PBEKeySpec(password,
|
||||
pKey.getSalt(),
|
||||
pKey.getIterationCount(),
|
||||
encoding.length*8);
|
||||
try {
|
||||
PBEKeySpec spec =
|
||||
new PBEKeySpec(pKey.getPassword(),
|
||||
pKey.getSalt(),
|
||||
pKey.getIterationCount(),
|
||||
pKey.getEncoded().length*8);
|
||||
return new PBKDF2KeyImpl(spec, "HmacSHA1");
|
||||
} catch (InvalidKeySpecException re) {
|
||||
InvalidKeyException ike = new InvalidKeyException
|
||||
("Invalid key component(s)");
|
||||
ike.initCause(re);
|
||||
throw ike;
|
||||
} finally {
|
||||
if (password != null) {
|
||||
Arrays.fill(password, (char) 0);
|
||||
spec.clearPassword();
|
||||
}
|
||||
Arrays.fill(encoding, (byte)0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2021, 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
|
||||
@ -73,6 +73,7 @@ final class PBKDF2KeyImpl implements javax.crypto.interfaces.PBEKey {
|
||||
int len = bb.limit();
|
||||
byte[] passwdBytes = new byte[len];
|
||||
bb.get(passwdBytes, 0, len);
|
||||
bb.clear().put(new byte[len]);
|
||||
|
||||
return passwdBytes;
|
||||
}
|
||||
@ -159,7 +160,7 @@ final class PBKDF2KeyImpl implements javax.crypto.interfaces.PBEKey {
|
||||
}
|
||||
@Override
|
||||
public byte[] getEncoded() {
|
||||
return password;
|
||||
return password.clone();
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
@ -225,6 +226,10 @@ final class PBKDF2KeyImpl implements javax.crypto.interfaces.PBEKey {
|
||||
return iterCount;
|
||||
}
|
||||
|
||||
public void clearPassword() {
|
||||
Arrays.fill(passwd, (char)0);
|
||||
}
|
||||
|
||||
public char[] getPassword() {
|
||||
// The password is zeroized by finalize()
|
||||
// The reachability fence ensures finalize() isn't called early
|
||||
@ -282,7 +287,7 @@ final class PBKDF2KeyImpl implements javax.crypto.interfaces.PBEKey {
|
||||
*/
|
||||
@java.io.Serial
|
||||
private Object writeReplace() throws ObjectStreamException {
|
||||
return new KeyRep(KeyRep.Type.SECRET, getAlgorithm(),
|
||||
getFormat(), getEncoded());
|
||||
return new KeyRep(KeyRep.Type.SECRET, getAlgorithm(),
|
||||
getFormat(), key);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2021, 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
|
||||
@ -174,18 +174,25 @@ abstract class PBMAC1Core extends HmacCore {
|
||||
Arrays.fill(passwdChars, '\0');
|
||||
}
|
||||
|
||||
SecretKey s;
|
||||
PBKDF2KeyImpl s = null;
|
||||
PBKDF2Core kdf = getKDFImpl(kdfAlgo);
|
||||
byte[] derivedKey;
|
||||
try {
|
||||
s = kdf.engineGenerateSecret(pbeSpec);
|
||||
s = (PBKDF2KeyImpl)kdf.engineGenerateSecret(pbeSpec);
|
||||
derivedKey = s.getEncoded();
|
||||
} catch (InvalidKeySpecException ikse) {
|
||||
InvalidKeyException ike =
|
||||
new InvalidKeyException("Cannot construct PBE key");
|
||||
ike.initCause(ikse);
|
||||
throw ike;
|
||||
} finally {
|
||||
pbeSpec.clearPassword();
|
||||
if (s != null) {
|
||||
s.clearPassword();
|
||||
}
|
||||
}
|
||||
byte[] derivedKey = s.getEncoded();
|
||||
SecretKey cipherKey = new SecretKeySpec(derivedKey, kdfAlgo);
|
||||
Arrays.fill(derivedKey, (byte)0);
|
||||
|
||||
super.engineInit(cipherKey, null);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2021, 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,12 +25,12 @@
|
||||
|
||||
package com.sun.crypto.provider;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.*;
|
||||
import java.security.spec.*;
|
||||
import java.util.Arrays;
|
||||
import javax.crypto.*;
|
||||
import javax.crypto.spec.*;
|
||||
import javax.security.auth.DestroyFailedException;
|
||||
|
||||
/**
|
||||
* This class implements password-base encryption algorithm with
|
||||
@ -108,7 +108,6 @@ final class PKCS12PBECipherCore {
|
||||
|
||||
byte[] Ai;
|
||||
byte[] B = new byte[v];
|
||||
byte[] tmp = new byte[v];
|
||||
|
||||
int i = 0;
|
||||
for (; ; i++, n -= u) {
|
||||
@ -118,37 +117,45 @@ final class PKCS12PBECipherCore {
|
||||
for (int r = 1; r < ic; r++)
|
||||
Ai = sha.digest(Ai);
|
||||
System.arraycopy(Ai, 0, key, u * i, Math.min(n, u));
|
||||
if (i + 1 == c)
|
||||
if (i + 1 == c) {
|
||||
break;
|
||||
concat(Ai, B, 0, B.length);
|
||||
BigInteger B1;
|
||||
B1 = new BigInteger(1, B).add(BigInteger.ONE);
|
||||
}
|
||||
concat(Ai, B, 0, v);
|
||||
addOne(v, B); // add 1 into B
|
||||
|
||||
for (int j = 0; j < I.length; j += v) {
|
||||
BigInteger Ij;
|
||||
int trunc;
|
||||
|
||||
if (tmp.length != v)
|
||||
tmp = new byte[v];
|
||||
System.arraycopy(I, j, tmp, 0, v);
|
||||
Ij = new BigInteger(1, tmp);
|
||||
Ij = Ij.add(B1);
|
||||
tmp = Ij.toByteArray();
|
||||
trunc = tmp.length - v;
|
||||
if (trunc >= 0) {
|
||||
System.arraycopy(tmp, trunc, I, j, v);
|
||||
} else if (trunc < 0) {
|
||||
Arrays.fill(I, j, j + (-trunc), (byte)0);
|
||||
System.arraycopy(tmp, 0, I, j + (-trunc), tmp.length);
|
||||
}
|
||||
addTwo(v, B, I, j); // add B into I from j
|
||||
}
|
||||
}
|
||||
Arrays.fill(I, (byte)0);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("internal error: " + e);
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
// Add 1 to b (as integer)
|
||||
private static void addOne(int len, byte[] b) {
|
||||
for (int i = len - 1; i >= 0; i--) {
|
||||
if ((b[i] & 0xff) != 255) {
|
||||
b[i]++;
|
||||
break;
|
||||
} else {
|
||||
b[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add src (as integer) to dst from offset (as integer)
|
||||
private static void addTwo(int len, byte[] src, byte[] dst, int offset) {
|
||||
int carry = 0;
|
||||
for (int i = len - 1; i >= 0; i--) {
|
||||
int sum = (src[i] & 0xff) + (dst[i + offset] & 0xff) + carry;
|
||||
carry = sum >> 8;
|
||||
dst[i + offset] = (byte)sum;
|
||||
}
|
||||
}
|
||||
|
||||
private static int roundup(int x, int y) {
|
||||
return ((x + (y - 1)) / y) * y;
|
||||
}
|
||||
@ -341,17 +348,26 @@ final class PKCS12PBECipherCore {
|
||||
byte[] derivedKey = derive(passwdChars, salt, iCount,
|
||||
keySize, CIPHER_KEY);
|
||||
SecretKey cipherKey = new SecretKeySpec(derivedKey, algo);
|
||||
Arrays.fill(derivedKey, (byte)0);
|
||||
|
||||
if (cipherImpl != null && cipherImpl instanceof ARCFOURCipher) {
|
||||
((ARCFOURCipher)cipherImpl).engineInit(opmode, cipherKey, random);
|
||||
try {
|
||||
if (cipherImpl != null && cipherImpl instanceof ARCFOURCipher) {
|
||||
((ARCFOURCipher) cipherImpl).engineInit(opmode, cipherKey, random);
|
||||
|
||||
} else {
|
||||
byte[] derivedIv = derive(passwdChars, salt, iCount, 8,
|
||||
CIPHER_IV);
|
||||
IvParameterSpec ivSpec = new IvParameterSpec(derivedIv, 0, 8);
|
||||
} else {
|
||||
byte[] derivedIv = derive(passwdChars, salt, iCount, 8,
|
||||
CIPHER_IV);
|
||||
IvParameterSpec ivSpec = new IvParameterSpec(derivedIv, 0, 8);
|
||||
|
||||
// initialize the underlying cipher
|
||||
cipher.init(opmode, cipherKey, ivSpec, random);
|
||||
// initialize the underlying cipher
|
||||
cipher.init(opmode, cipherKey, ivSpec, random);
|
||||
}
|
||||
} finally {
|
||||
try {
|
||||
cipherKey.destroy();
|
||||
} catch (DestroyFailedException e) {
|
||||
// Ignore the failure
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
Arrays.fill(passwdChars, '\0');
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2021, 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
|
||||
@ -27,6 +27,8 @@ package com.sun.crypto.provider;
|
||||
|
||||
import java.math.*;
|
||||
import java.io.*;
|
||||
import java.util.Arrays;
|
||||
|
||||
import sun.security.x509.AlgorithmId;
|
||||
import sun.security.util.*;
|
||||
|
||||
@ -62,23 +64,27 @@ final class PrivateKeyInfo {
|
||||
PrivateKeyInfo(byte[] encoded) throws IOException {
|
||||
DerValue val = new DerValue(encoded);
|
||||
|
||||
if (val.tag != DerValue.tag_Sequence)
|
||||
throw new IOException("private key parse error: not a sequence");
|
||||
try {
|
||||
if (val.tag != DerValue.tag_Sequence)
|
||||
throw new IOException("private key parse error: not a sequence");
|
||||
|
||||
// version
|
||||
BigInteger parsedVersion = val.data.getBigInteger();
|
||||
if (!parsedVersion.equals(VERSION)) {
|
||||
throw new IOException("version mismatch: (supported: " +
|
||||
VERSION + ", parsed: " + parsedVersion);
|
||||
// version
|
||||
BigInteger parsedVersion = val.data.getBigInteger();
|
||||
if (!parsedVersion.equals(VERSION)) {
|
||||
throw new IOException("version mismatch: (supported: " +
|
||||
VERSION + ", parsed: " + parsedVersion);
|
||||
}
|
||||
|
||||
// privateKeyAlgorithm
|
||||
this.algid = AlgorithmId.parse(val.data.getDerValue());
|
||||
|
||||
// privateKey
|
||||
this.privkey = val.data.getOctetString();
|
||||
|
||||
// OPTIONAL attributes not supported yet
|
||||
} finally {
|
||||
val.clear();
|
||||
}
|
||||
|
||||
// privateKeyAlgorithm
|
||||
this.algid = AlgorithmId.parse(val.data.getDerValue());
|
||||
|
||||
// privateKey
|
||||
this.privkey = val.data.getOctetString();
|
||||
|
||||
// OPTIONAL attributes not supported yet
|
||||
}
|
||||
|
||||
/**
|
||||
@ -87,4 +93,8 @@ final class PrivateKeyInfo {
|
||||
AlgorithmId getAlgorithm() {
|
||||
return this.algid;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
Arrays.fill(privkey, (byte)0);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2021, 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
|
||||
@ -27,6 +27,7 @@ package com.sun.crypto.provider;
|
||||
|
||||
import java.security.*;
|
||||
import java.security.spec.*;
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.crypto.*;
|
||||
import javax.crypto.spec.RC2ParameterSpec;
|
||||
@ -133,6 +134,7 @@ public final class RC2Cipher extends CipherSpi {
|
||||
|
||||
protected int engineGetKeySize(Key key) throws InvalidKeyException {
|
||||
byte[] keyBytes = CipherCore.getKeyBytes(key);
|
||||
Arrays.fill(keyBytes, (byte)0);
|
||||
RC2Crypt.checkKey(key.getAlgorithm(), keyBytes.length);
|
||||
return keyBytes.length << 3;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2021, 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
|
||||
@ -27,6 +27,7 @@ package com.sun.crypto.provider;
|
||||
|
||||
import java.security.*;
|
||||
import java.security.spec.AlgorithmParameterSpec;
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.crypto.*;
|
||||
import javax.crypto.spec.*;
|
||||
@ -86,16 +87,18 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi {
|
||||
throw new IllegalStateException(
|
||||
"TlsKeyMaterialGenerator must be initialized");
|
||||
}
|
||||
byte[] masterSecret = spec.getMasterSecret().getEncoded();
|
||||
try {
|
||||
return engineGenerateKey0();
|
||||
return engineGenerateKey0(masterSecret);
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw new ProviderException(e);
|
||||
} finally {
|
||||
Arrays.fill(masterSecret, (byte)0);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private SecretKey engineGenerateKey0() throws GeneralSecurityException {
|
||||
byte[] masterSecret = spec.getMasterSecret().getEncoded();
|
||||
private SecretKey engineGenerateKey0(byte[] masterSecret) throws GeneralSecurityException {
|
||||
|
||||
byte[] clientRandom = spec.getClientRandom();
|
||||
byte[] serverRandom = spec.getServerRandom();
|
||||
@ -116,7 +119,7 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi {
|
||||
int keyBlockLen = macLength + keyLength
|
||||
+ (isExportable ? 0 : ivLength);
|
||||
keyBlockLen <<= 1;
|
||||
byte[] keyBlock = new byte[keyBlockLen];
|
||||
byte[] keyBlock;
|
||||
|
||||
// These may be used again later for exportable suite calculations.
|
||||
MessageDigest md5 = null;
|
||||
@ -169,16 +172,11 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi {
|
||||
|
||||
int ofs = 0;
|
||||
if (macLength != 0) {
|
||||
byte[] tmp = new byte[macLength];
|
||||
|
||||
// mac keys
|
||||
System.arraycopy(keyBlock, ofs, tmp, 0, macLength);
|
||||
clientMacKey = new SecretKeySpec(keyBlock, ofs, macLength, "Mac");
|
||||
ofs += macLength;
|
||||
clientMacKey = new SecretKeySpec(tmp, "Mac");
|
||||
|
||||
System.arraycopy(keyBlock, ofs, tmp, 0, macLength);
|
||||
serverMacKey = new SecretKeySpec(keyBlock, ofs, macLength, "Mac");
|
||||
ofs += macLength;
|
||||
serverMacKey = new SecretKeySpec(tmp, "Mac");
|
||||
}
|
||||
|
||||
if (keyLength == 0) { // SSL_RSA_WITH_NULL_* ciphersuites
|
||||
@ -196,82 +194,89 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi {
|
||||
System.arraycopy(keyBlock, ofs, serverKeyBytes, 0, keyLength);
|
||||
ofs += keyLength;
|
||||
|
||||
if (isExportable == false) {
|
||||
// cipher keys
|
||||
clientCipherKey = new SecretKeySpec(clientKeyBytes, alg);
|
||||
serverCipherKey = new SecretKeySpec(serverKeyBytes, alg);
|
||||
|
||||
// IV keys if needed.
|
||||
if (ivLength != 0) {
|
||||
byte[] tmp = new byte[ivLength];
|
||||
|
||||
System.arraycopy(keyBlock, ofs, tmp, 0, ivLength);
|
||||
ofs += ivLength;
|
||||
clientIv = new IvParameterSpec(tmp);
|
||||
|
||||
System.arraycopy(keyBlock, ofs, tmp, 0, ivLength);
|
||||
ofs += ivLength;
|
||||
serverIv = new IvParameterSpec(tmp);
|
||||
}
|
||||
} else {
|
||||
// if exportable suites, calculate the alternate
|
||||
// cipher key expansion and IV generation
|
||||
if (protocolVersion >= 0x0302) {
|
||||
// TLS 1.1+
|
||||
throw new RuntimeException(
|
||||
"Internal Error: TLS 1.1+ should not be negotiating" +
|
||||
"exportable ciphersuites");
|
||||
} else if (protocolVersion == 0x0301) {
|
||||
// TLS 1.0
|
||||
byte[] seed = concat(clientRandom, serverRandom);
|
||||
|
||||
byte[] tmp = doTLS10PRF(clientKeyBytes,
|
||||
LABEL_CLIENT_WRITE_KEY, seed, expandedKeyLength, md5, sha);
|
||||
clientCipherKey = new SecretKeySpec(tmp, alg);
|
||||
|
||||
tmp = doTLS10PRF(serverKeyBytes, LABEL_SERVER_WRITE_KEY, seed,
|
||||
expandedKeyLength, md5, sha);
|
||||
serverCipherKey = new SecretKeySpec(tmp, alg);
|
||||
try {
|
||||
if (isExportable == false) {
|
||||
// cipher keys
|
||||
clientCipherKey = new SecretKeySpec(clientKeyBytes, alg);
|
||||
serverCipherKey = new SecretKeySpec(serverKeyBytes, alg);
|
||||
|
||||
// IV keys if needed.
|
||||
if (ivLength != 0) {
|
||||
tmp = new byte[ivLength];
|
||||
byte[] block = doTLS10PRF(null, LABEL_IV_BLOCK, seed,
|
||||
ivLength << 1, md5, sha);
|
||||
System.arraycopy(block, 0, tmp, 0, ivLength);
|
||||
clientIv = new IvParameterSpec(tmp);
|
||||
System.arraycopy(block, ivLength, tmp, 0, ivLength);
|
||||
serverIv = new IvParameterSpec(tmp);
|
||||
clientIv = new IvParameterSpec(keyBlock, ofs, ivLength);
|
||||
ofs += ivLength;
|
||||
serverIv = new IvParameterSpec(keyBlock, ofs, ivLength);
|
||||
ofs += ivLength;
|
||||
}
|
||||
} else {
|
||||
// SSLv3
|
||||
byte[] tmp = new byte[expandedKeyLength];
|
||||
// if exportable suites, calculate the alternate
|
||||
// cipher key expansion and IV generation
|
||||
if (protocolVersion >= 0x0302) {
|
||||
// TLS 1.1+
|
||||
throw new RuntimeException(
|
||||
"Internal Error: TLS 1.1+ should not be negotiating" +
|
||||
"exportable ciphersuites");
|
||||
} else if (protocolVersion == 0x0301) {
|
||||
// TLS 1.0
|
||||
byte[] seed = concat(clientRandom, serverRandom);
|
||||
|
||||
md5.update(clientKeyBytes);
|
||||
md5.update(clientRandom);
|
||||
md5.update(serverRandom);
|
||||
System.arraycopy(md5.digest(), 0, tmp, 0, expandedKeyLength);
|
||||
clientCipherKey = new SecretKeySpec(tmp, alg);
|
||||
byte[] tmp = doTLS10PRF(clientKeyBytes,
|
||||
LABEL_CLIENT_WRITE_KEY, seed, expandedKeyLength, md5, sha);
|
||||
clientCipherKey = new SecretKeySpec(tmp, alg);
|
||||
Arrays.fill(tmp, (byte) 0);
|
||||
|
||||
md5.update(serverKeyBytes);
|
||||
md5.update(serverRandom);
|
||||
md5.update(clientRandom);
|
||||
System.arraycopy(md5.digest(), 0, tmp, 0, expandedKeyLength);
|
||||
serverCipherKey = new SecretKeySpec(tmp, alg);
|
||||
tmp = doTLS10PRF(serverKeyBytes, LABEL_SERVER_WRITE_KEY, seed,
|
||||
expandedKeyLength, md5, sha);
|
||||
serverCipherKey = new SecretKeySpec(tmp, alg);
|
||||
Arrays.fill(tmp, (byte) 0);
|
||||
|
||||
if (ivLength != 0) {
|
||||
tmp = new byte[ivLength];
|
||||
if (ivLength != 0) {
|
||||
byte[] block = doTLS10PRF(null, LABEL_IV_BLOCK, seed,
|
||||
ivLength << 1, md5, sha);
|
||||
clientIv = new IvParameterSpec(block, 0, ivLength);
|
||||
serverIv = new IvParameterSpec(block, ivLength, ivLength);
|
||||
}
|
||||
} else {
|
||||
// SSLv3
|
||||
byte[] tmp = new byte[expandedKeyLength];
|
||||
byte[] digest;
|
||||
|
||||
md5.update(clientKeyBytes);
|
||||
md5.update(clientRandom);
|
||||
md5.update(serverRandom);
|
||||
System.arraycopy(md5.digest(), 0, tmp, 0, ivLength);
|
||||
clientIv = new IvParameterSpec(tmp);
|
||||
digest = md5.digest();
|
||||
System.arraycopy(digest, 0, tmp, 0, expandedKeyLength);
|
||||
clientCipherKey = new SecretKeySpec(tmp, alg);
|
||||
Arrays.fill(digest, (byte) 0);
|
||||
|
||||
md5.update(serverKeyBytes);
|
||||
md5.update(serverRandom);
|
||||
md5.update(clientRandom);
|
||||
System.arraycopy(md5.digest(), 0, tmp, 0, ivLength);
|
||||
serverIv = new IvParameterSpec(tmp);
|
||||
digest = md5.digest();
|
||||
System.arraycopy(digest, 0, tmp, 0, expandedKeyLength);
|
||||
serverCipherKey = new SecretKeySpec(tmp, alg);
|
||||
Arrays.fill(digest, (byte) 0);
|
||||
|
||||
Arrays.fill(tmp, (byte) 0);
|
||||
|
||||
if (ivLength != 0) {
|
||||
tmp = new byte[ivLength];
|
||||
|
||||
md5.update(clientRandom);
|
||||
md5.update(serverRandom);
|
||||
System.arraycopy(md5.digest(), 0, tmp, 0, ivLength);
|
||||
clientIv = new IvParameterSpec(tmp);
|
||||
|
||||
md5.update(serverRandom);
|
||||
md5.update(clientRandom);
|
||||
System.arraycopy(md5.digest(), 0, tmp, 0, ivLength);
|
||||
serverIv = new IvParameterSpec(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
Arrays.fill(serverKeyBytes, (byte) 0);
|
||||
Arrays.fill(clientKeyBytes, (byte) 0);
|
||||
Arrays.fill(keyBlock, (byte) 0);
|
||||
}
|
||||
|
||||
return new TlsKeyMaterialSpec(clientMacKey, serverMacKey,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2021, 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
|
||||
@ -27,6 +27,7 @@ package com.sun.crypto.provider;
|
||||
|
||||
import java.security.*;
|
||||
import java.security.spec.AlgorithmParameterSpec;
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.crypto.*;
|
||||
|
||||
@ -135,20 +136,26 @@ public final class TlsMasterSecretGenerator extends KeyGeneratorSpi {
|
||||
sha.update(clientRandom);
|
||||
sha.update(serverRandom);
|
||||
sha.digest(tmp, 0, 20);
|
||||
sha.reset();
|
||||
|
||||
md5.update(premaster);
|
||||
md5.update(tmp);
|
||||
md5.digest(master, i << 4, 16);
|
||||
md5.reset();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// master is referenced inside the TlsMasterSecretKey.
|
||||
// Do not touch it anymore.
|
||||
return new TlsMasterSecretKey(master, premasterMajor,
|
||||
premasterMinor);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new ProviderException(e);
|
||||
} catch (DigestException e) {
|
||||
throw new ProviderException(e);
|
||||
} finally {
|
||||
if (premaster != null) {
|
||||
Arrays.fill(premaster, (byte)0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2021, 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
|
||||
@ -162,9 +162,17 @@ abstract class TlsPrfGenerator extends KeyGeneratorSpi {
|
||||
spec.getPRFHashAlg(), spec.getPRFHashLength(),
|
||||
spec.getPRFBlockSize()) :
|
||||
doTLS10PRF(secret, labelBytes, spec.getSeed(), n));
|
||||
return new SecretKeySpec(prfBytes, "TlsPrf");
|
||||
try {
|
||||
return new SecretKeySpec(prfBytes, "TlsPrf");
|
||||
} finally {
|
||||
Arrays.fill(prfBytes, (byte)0);
|
||||
}
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw new ProviderException("Could not generate PRF", e);
|
||||
} finally {
|
||||
if (secret != null) {
|
||||
Arrays.fill(secret, (byte) 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -257,6 +265,7 @@ abstract class TlsPrfGenerator extends KeyGeneratorSpi {
|
||||
if (seclen > 64) { // 64: block size of HMAC-MD5
|
||||
md5.update(secret, 0, seclen);
|
||||
secKey = md5.digest();
|
||||
md5.reset();
|
||||
keyLen = secKey.length;
|
||||
}
|
||||
expand(md5, 16, secKey, 0, keyLen, labelBytes, seed, output,
|
||||
@ -267,6 +276,7 @@ abstract class TlsPrfGenerator extends KeyGeneratorSpi {
|
||||
if (seclen > 64) { // 64: block size of HMAC-SHA1
|
||||
sha.update(secret, off, seclen);
|
||||
secKey = sha.digest();
|
||||
sha.reset();
|
||||
keyLen = secKey.length;
|
||||
off = 0;
|
||||
}
|
||||
@ -351,12 +361,15 @@ abstract class TlsPrfGenerator extends KeyGeneratorSpi {
|
||||
digest.update(tmp);
|
||||
digest.digest(tmp, 0, hmacSize);
|
||||
|
||||
digest.reset();
|
||||
|
||||
int k = Math.min(hmacSize, remaining);
|
||||
for (int i = 0; i < k; i++) {
|
||||
output[ofs++] ^= tmp[i];
|
||||
}
|
||||
remaining -= k;
|
||||
}
|
||||
Arrays.fill(tmp, (byte)0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2021, 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
|
||||
@ -27,6 +27,7 @@ package com.sun.crypto.provider;
|
||||
|
||||
import java.security.*;
|
||||
import java.security.spec.AlgorithmParameterSpec;
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.crypto.*;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
@ -87,7 +88,11 @@ public final class TlsRsaPremasterSecretGenerator extends KeyGeneratorSpi {
|
||||
b[0] = (byte)spec.getMajorVersion();
|
||||
b[1] = (byte)spec.getMinorVersion();
|
||||
|
||||
return new SecretKeySpec(b, "TlsRsaPremasterSecret");
|
||||
try {
|
||||
return new SecretKeySpec(b, "TlsRsaPremasterSecret");
|
||||
} finally {
|
||||
Arrays.fill(b, (byte)0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -688,7 +688,23 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
|
||||
* @see #bitLength()
|
||||
*/
|
||||
public BigInteger(int numBits, Random rnd) {
|
||||
this(1, randomBits(numBits, rnd));
|
||||
byte[] magnitude = randomBits(numBits, rnd);
|
||||
|
||||
try {
|
||||
// stripLeadingZeroBytes() returns a zero length array if len == 0
|
||||
this.mag = stripLeadingZeroBytes(magnitude, 0, magnitude.length);
|
||||
|
||||
if (this.mag.length == 0) {
|
||||
this.signum = 0;
|
||||
} else {
|
||||
this.signum = 1;
|
||||
}
|
||||
if (mag.length >= MAX_MAG_LENGTH) {
|
||||
checkRange();
|
||||
}
|
||||
} finally {
|
||||
Arrays.fill(magnitude, (byte)0);
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] randomBits(int numBits, Random rnd) {
|
||||
|
@ -159,8 +159,14 @@ class MutableBigInteger {
|
||||
* supposed to modify the returned array.
|
||||
*/
|
||||
private int[] getMagnitudeArray() {
|
||||
if (offset > 0 || value.length != intLen)
|
||||
return Arrays.copyOfRange(value, offset, offset + intLen);
|
||||
if (offset > 0 || value.length != intLen) {
|
||||
// Shrink value to be the total magnitude
|
||||
int[] tmp = Arrays.copyOfRange(value, offset, offset + intLen);
|
||||
Arrays.fill(value, 0);
|
||||
offset = 0;
|
||||
intLen = tmp.length;
|
||||
value = tmp;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2021, 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,11 @@
|
||||
|
||||
package java.security.spec;
|
||||
|
||||
import jdk.internal.access.JavaSecuritySpecAccess;
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* This class represents a public or private key in encoded format.
|
||||
*
|
||||
@ -45,7 +50,17 @@ public abstract class EncodedKeySpec implements KeySpec {
|
||||
private byte[] encodedKey;
|
||||
private String algorithmName;
|
||||
|
||||
/**
|
||||
static {
|
||||
SharedSecrets.setJavaSecuritySpecAccess(
|
||||
new JavaSecuritySpecAccess() {
|
||||
@Override
|
||||
public void clearEncodedKeySpec(EncodedKeySpec keySpec) {
|
||||
keySpec.clear();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@code EncodedKeySpec} with the given encoded key.
|
||||
*
|
||||
* @param encodedKey the encoded key. The contents of the
|
||||
@ -125,4 +140,11 @@ public abstract class EncodedKeySpec implements KeySpec {
|
||||
* @return a string representation of the encoding format.
|
||||
*/
|
||||
public abstract String getFormat();
|
||||
|
||||
/**
|
||||
* Clear the encoding inside.
|
||||
*/
|
||||
void clear() {
|
||||
Arrays.fill(encodedKey, (byte)0);
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ import java.security.InvalidKeyException;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.NoSuchProviderException;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* This class enables a programmer to create an object and protect its
|
||||
@ -171,10 +172,11 @@ public class SealedObject implements Serializable {
|
||||
*/
|
||||
try {
|
||||
this.encryptedContent = c.doFinal(content);
|
||||
}
|
||||
catch (BadPaddingException ex) {
|
||||
} catch (BadPaddingException ex) {
|
||||
// if sealing is encryption only
|
||||
// Should never happen??
|
||||
} finally {
|
||||
Arrays.fill(content, (byte)0);
|
||||
}
|
||||
|
||||
// Save the parameters
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2021, 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,8 +25,12 @@
|
||||
|
||||
package javax.crypto.spec;
|
||||
|
||||
import jdk.internal.access.JavaxCryptoSpecAccess;
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.security.spec.KeySpec;
|
||||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
import javax.crypto.SecretKey;
|
||||
|
||||
@ -66,6 +70,16 @@ public class SecretKeySpec implements KeySpec, SecretKey {
|
||||
*/
|
||||
private String algorithm;
|
||||
|
||||
static {
|
||||
SharedSecrets.setJavaxCryptoSpecAccess(
|
||||
new JavaxCryptoSpecAccess() {
|
||||
@Override
|
||||
public void clearSecretKeySpec(SecretKeySpec keySpec) {
|
||||
keySpec.clear();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a secret key from the given byte array.
|
||||
*
|
||||
@ -227,7 +241,19 @@ public class SecretKeySpec implements KeySpec, SecretKey {
|
||||
}
|
||||
|
||||
byte[] thatKey = ((SecretKey)obj).getEncoded();
|
||||
try {
|
||||
return MessageDigest.isEqual(this.key, thatKey);
|
||||
} finally {
|
||||
if (thatKey != null) {
|
||||
Arrays.fill(thatKey, (byte)0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return MessageDigest.isEqual(this.key, thatKey);
|
||||
/**
|
||||
* Clear the key bytes inside.
|
||||
*/
|
||||
void clear() {
|
||||
Arrays.fill(key, (byte)0);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2021, 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package jdk.internal.access;
|
||||
|
||||
import java.security.spec.EncodedKeySpec;
|
||||
|
||||
public interface JavaSecuritySpecAccess {
|
||||
void clearEncodedKeySpec(EncodedKeySpec keySpec);
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2021, 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package jdk.internal.access;
|
||||
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
public interface JavaxCryptoSpecAccess {
|
||||
void clearSecretKeySpec(SecretKeySpec keySpec);
|
||||
}
|
@ -26,9 +26,11 @@
|
||||
package jdk.internal.access;
|
||||
|
||||
import javax.crypto.SealedObject;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.io.ObjectInputFilter;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.module.ModuleDescriptor;
|
||||
import java.security.spec.EncodedKeySpec;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.jar.JarFile;
|
||||
import java.io.Console;
|
||||
@ -76,7 +78,9 @@ public class SharedSecrets {
|
||||
private static JavaUtilResourceBundleAccess javaUtilResourceBundleAccess;
|
||||
private static JavaSecurityAccess javaSecurityAccess;
|
||||
private static JavaSecuritySignatureAccess javaSecuritySignatureAccess;
|
||||
private static JavaSecuritySpecAccess javaSecuritySpecAccess;
|
||||
private static JavaxCryptoSealedObjectAccess javaxCryptoSealedObjectAccess;
|
||||
private static JavaxCryptoSpecAccess javaxCryptoSpecAccess;
|
||||
|
||||
public static void setJavaUtilCollectionAccess(JavaUtilCollectionAccess juca) {
|
||||
javaUtilCollectionAccess = juca;
|
||||
@ -398,6 +402,28 @@ public class SharedSecrets {
|
||||
return access;
|
||||
}
|
||||
|
||||
public static void setJavaSecuritySpecAccess(JavaSecuritySpecAccess jssa) {
|
||||
javaSecuritySpecAccess = jssa;
|
||||
}
|
||||
|
||||
public static JavaSecuritySpecAccess getJavaSecuritySpecAccess() {
|
||||
if (javaSecuritySpecAccess == null) {
|
||||
ensureClassInitialized(EncodedKeySpec.class);
|
||||
}
|
||||
return javaSecuritySpecAccess;
|
||||
}
|
||||
|
||||
public static void setJavaxCryptoSpecAccess(JavaxCryptoSpecAccess jcsa) {
|
||||
javaxCryptoSpecAccess = jcsa;
|
||||
}
|
||||
|
||||
public static JavaxCryptoSpecAccess getJavaxCryptoSpecAccess() {
|
||||
if (javaxCryptoSpecAccess == null) {
|
||||
ensureClassInitialized(SecretKeySpec.class);
|
||||
}
|
||||
return javaxCryptoSpecAccess;
|
||||
}
|
||||
|
||||
public static void setJavaxCryptoSealedObjectAccess(JavaxCryptoSealedObjectAccess jcsoa) {
|
||||
javaxCryptoSealedObjectAccess = jcsoa;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 2021, 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
|
||||
@ -37,6 +37,7 @@ import java.security.spec.InvalidKeySpecException;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
import java.util.Arrays;
|
||||
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
import sun.security.x509.*;
|
||||
import sun.security.util.*;
|
||||
|
||||
@ -95,8 +96,9 @@ public class PKCS8Key implements PrivateKey {
|
||||
}
|
||||
|
||||
private void decode(InputStream is) throws InvalidKeyException {
|
||||
DerValue val = null;
|
||||
try {
|
||||
DerValue val = new DerValue(is);
|
||||
val = new DerValue(is);
|
||||
if (val.tag != DerValue.tag_Sequence) {
|
||||
throw new InvalidKeyException("invalid key format");
|
||||
}
|
||||
@ -106,7 +108,7 @@ public class PKCS8Key implements PrivateKey {
|
||||
throw new InvalidKeyException("unknown version: " + version);
|
||||
}
|
||||
algid = AlgorithmId.parse (val.data.getDerValue ());
|
||||
key = val.data.getOctetString ();
|
||||
key = val.data.getOctetString();
|
||||
|
||||
DerValue next;
|
||||
if (val.data.available() == 0) {
|
||||
@ -131,11 +133,15 @@ public class PKCS8Key implements PrivateKey {
|
||||
throw new InvalidKeyException("Extra bytes");
|
||||
} catch (IOException e) {
|
||||
throw new InvalidKeyException("IOException : " + e.getMessage());
|
||||
} finally {
|
||||
if (val != null) {
|
||||
val.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct PKCS#8 subject public key from a DER value. If a
|
||||
* Construct PKCS#8 subject public key from a DER encoding. If a
|
||||
* security provider supports the key algorithm with a specific class,
|
||||
* a PrivateKey from the provider is returned. Otherwise, a raw
|
||||
* PKCS8Key object is returned.
|
||||
@ -145,21 +151,29 @@ public class PKCS8Key implements PrivateKey {
|
||||
* information. Also, when a key (or algorithm) needs some special
|
||||
* handling, that specific need can be accommodated.
|
||||
*
|
||||
* @param in the DER-encoded SubjectPublicKeyInfo value
|
||||
* @param encoded the DER-encoded SubjectPublicKeyInfo value
|
||||
* @exception IOException on data format errors
|
||||
*/
|
||||
public static PrivateKey parseKey(DerValue in) throws IOException {
|
||||
public static PrivateKey parseKey(byte[] encoded) throws IOException {
|
||||
try {
|
||||
PKCS8Key rawKey = new PKCS8Key(in.toByteArray());
|
||||
PKCS8EncodedKeySpec pkcs8KeySpec
|
||||
= new PKCS8EncodedKeySpec(rawKey.getEncoded());
|
||||
PKCS8Key rawKey = new PKCS8Key(encoded);
|
||||
byte[] internal = rawKey.getEncodedInternal();
|
||||
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(internal);
|
||||
PrivateKey result = null;
|
||||
try {
|
||||
return KeyFactory.getInstance(rawKey.algid.getName())
|
||||
result = KeyFactory.getInstance(rawKey.algid.getName())
|
||||
.generatePrivate(pkcs8KeySpec);
|
||||
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
|
||||
// Ignore and return raw key
|
||||
return rawKey;
|
||||
result = rawKey;
|
||||
} finally {
|
||||
if (result != rawKey) {
|
||||
rawKey.clear();
|
||||
}
|
||||
SharedSecrets.getJavaSecuritySpecAccess()
|
||||
.clearEncodedKeySpec(pkcs8KeySpec);
|
||||
}
|
||||
return result;
|
||||
} catch (InvalidKeyException e) {
|
||||
throw new IOException("corrupt private key", e);
|
||||
}
|
||||
@ -183,14 +197,9 @@ public class PKCS8Key implements PrivateKey {
|
||||
* Returns the DER-encoded form of the key as a byte array,
|
||||
* or {@code null} if an encoding error occurs.
|
||||
*/
|
||||
public synchronized byte[] getEncoded() {
|
||||
try {
|
||||
encode();
|
||||
return encodedKey.clone();
|
||||
} catch (InvalidKeyException e) {
|
||||
// ignored and return null
|
||||
}
|
||||
return null;
|
||||
public byte[] getEncoded() {
|
||||
byte[] b = getEncodedInternal();
|
||||
return (b == null) ? null : b.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -201,34 +210,34 @@ public class PKCS8Key implements PrivateKey {
|
||||
}
|
||||
|
||||
/**
|
||||
* DER-encodes this key as a byte array that can be retrieved
|
||||
* by the {@link #getEncoded()} method.
|
||||
* DER-encodes this key as a byte array stored inside this object
|
||||
* and return it.
|
||||
*
|
||||
* @exception InvalidKeyException if an encoding error occurs.
|
||||
* @return the encoding, or null if there is an I/O error.
|
||||
*/
|
||||
private void encode() throws InvalidKeyException {
|
||||
private synchronized byte[] getEncodedInternal() {
|
||||
if (encodedKey == null) {
|
||||
try {
|
||||
DerOutputStream out = new DerOutputStream ();
|
||||
DerOutputStream tmp = new DerOutputStream();
|
||||
tmp.putInteger(V1);
|
||||
algid.encode(tmp);
|
||||
tmp.putOctetString(key);
|
||||
out.write(DerValue.tag_Sequence, tmp);
|
||||
DerValue out = DerValue.wrap(DerValue.tag_Sequence, tmp);
|
||||
encodedKey = out.toByteArray();
|
||||
out.clear();
|
||||
} catch (IOException e) {
|
||||
throw new InvalidKeyException ("IOException : " +
|
||||
e.getMessage());
|
||||
// encodedKey is still null
|
||||
}
|
||||
}
|
||||
return encodedKey;
|
||||
}
|
||||
|
||||
@java.io.Serial
|
||||
protected Object writeReplace() throws java.io.ObjectStreamException {
|
||||
return new KeyRep(KeyRep.Type.PRIVATE,
|
||||
getAlgorithm(),
|
||||
getFormat(),
|
||||
getEncoded());
|
||||
getAlgorithm(),
|
||||
getFormat(),
|
||||
getEncodedInternal());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -258,11 +267,23 @@ public class PKCS8Key implements PrivateKey {
|
||||
if (this == object) {
|
||||
return true;
|
||||
}
|
||||
if (object instanceof Key) {
|
||||
if (object instanceof PKCS8Key) {
|
||||
// time-constant comparison
|
||||
return MessageDigest.isEqual(
|
||||
getEncoded(),
|
||||
((Key)object).getEncoded());
|
||||
getEncodedInternal(),
|
||||
((PKCS8Key)object).getEncodedInternal());
|
||||
} else if (object instanceof Key) {
|
||||
// time-constant comparison
|
||||
byte[] otherEncoded = ((Key)object).getEncoded();
|
||||
try {
|
||||
return MessageDigest.isEqual(
|
||||
getEncodedInternal(),
|
||||
otherEncoded);
|
||||
} finally {
|
||||
if (otherEncoded != null) {
|
||||
Arrays.fill(otherEncoded, (byte) 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -272,6 +293,13 @@ public class PKCS8Key implements PrivateKey {
|
||||
* which are equal will also have the same hashcode.
|
||||
*/
|
||||
public int hashCode() {
|
||||
return Arrays.hashCode(getEncoded());
|
||||
return Arrays.hashCode(getEncodedInternal());
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
if (encodedKey != null) {
|
||||
Arrays.fill(encodedKey, (byte)0);
|
||||
}
|
||||
Arrays.fill(key, (byte)0);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2021, 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
|
||||
@ -65,6 +65,7 @@ import javax.crypto.Mac;
|
||||
import javax.security.auth.DestroyFailedException;
|
||||
import javax.security.auth.x500.X500Principal;
|
||||
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
import sun.security.tools.KeyStoreUtil;
|
||||
import sun.security.util.*;
|
||||
@ -359,63 +360,87 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
|
||||
|
||||
key = RetryWithZero.run(pass -> {
|
||||
// Use JCE
|
||||
SecretKey skey = getPBEKey(pass);
|
||||
Cipher cipher = Cipher.getInstance(
|
||||
mapPBEParamsToAlgorithm(algOid, algParams));
|
||||
cipher.init(Cipher.DECRYPT_MODE, skey, algParams);
|
||||
SecretKey skey = getPBEKey(pass);
|
||||
try {
|
||||
cipher.init(Cipher.DECRYPT_MODE, skey, algParams);
|
||||
} finally {
|
||||
destroyPBEKey(skey);
|
||||
}
|
||||
byte[] keyInfo = cipher.doFinal(encryptedKey);
|
||||
/*
|
||||
* Parse the key algorithm and then use a JCA key factory
|
||||
* to re-create the key.
|
||||
*/
|
||||
DerValue val = new DerValue(keyInfo);
|
||||
DerInputStream in = val.toDerInputStream();
|
||||
int i = in.getInteger();
|
||||
DerValue[] value = in.getSequence(2);
|
||||
if (value.length < 1 || value.length > 2) {
|
||||
throw new IOException("Invalid length for AlgorithmIdentifier");
|
||||
}
|
||||
AlgorithmId algId = new AlgorithmId(value[0].getOID());
|
||||
String keyAlgo = algId.getName();
|
||||
|
||||
// decode private key
|
||||
if (entry instanceof PrivateKeyEntry) {
|
||||
KeyFactory kfac = KeyFactory.getInstance(keyAlgo);
|
||||
PKCS8EncodedKeySpec kspec = new PKCS8EncodedKeySpec(keyInfo);
|
||||
Key tmp = kfac.generatePrivate(kspec);
|
||||
|
||||
if (debug != null) {
|
||||
debug.println("Retrieved a protected private key at alias" +
|
||||
" '" + alias + "' (" +
|
||||
mapPBEParamsToAlgorithm(algOid, algParams) +
|
||||
" iterations: " + ic + ")");
|
||||
try {
|
||||
DerInputStream in = val.toDerInputStream();
|
||||
int i = in.getInteger();
|
||||
DerValue[] value = in.getSequence(2);
|
||||
if (value.length < 1 || value.length > 2) {
|
||||
throw new IOException("Invalid length for AlgorithmIdentifier");
|
||||
}
|
||||
return tmp;
|
||||
// decode secret key
|
||||
} else {
|
||||
byte[] keyBytes = in.getOctetString();
|
||||
SecretKeySpec secretKeySpec =
|
||||
new SecretKeySpec(keyBytes, keyAlgo);
|
||||
AlgorithmId algId = new AlgorithmId(value[0].getOID());
|
||||
String keyAlgo = algId.getName();
|
||||
|
||||
// Special handling required for PBE: needs a PBEKeySpec
|
||||
Key tmp;
|
||||
if (keyAlgo.startsWith("PBE")) {
|
||||
SecretKeyFactory sKeyFactory =
|
||||
SecretKeyFactory.getInstance(keyAlgo);
|
||||
KeySpec pbeKeySpec =
|
||||
sKeyFactory.getKeySpec(secretKeySpec, PBEKeySpec.class);
|
||||
tmp = sKeyFactory.generateSecret(pbeKeySpec);
|
||||
// decode private key
|
||||
if (entry instanceof PrivateKeyEntry) {
|
||||
KeyFactory kfac = KeyFactory.getInstance(keyAlgo);
|
||||
PKCS8EncodedKeySpec kspec = new PKCS8EncodedKeySpec(keyInfo);
|
||||
try {
|
||||
Key tmp = kfac.generatePrivate(kspec);
|
||||
|
||||
if (debug != null) {
|
||||
debug.println("Retrieved a protected private key at alias" +
|
||||
" '" + alias + "' (" +
|
||||
mapPBEParamsToAlgorithm(algOid, algParams) +
|
||||
" iterations: " + ic + ")");
|
||||
}
|
||||
return tmp;
|
||||
} finally {
|
||||
SharedSecrets.getJavaSecuritySpecAccess()
|
||||
.clearEncodedKeySpec(kspec);
|
||||
}
|
||||
// decode secret key
|
||||
} else {
|
||||
tmp = secretKeySpec;
|
||||
}
|
||||
byte[] keyBytes = in.getOctetString();
|
||||
SecretKeySpec secretKeySpec =
|
||||
new SecretKeySpec(keyBytes, keyAlgo);
|
||||
|
||||
if (debug != null) {
|
||||
debug.println("Retrieved a protected secret key at alias " +
|
||||
"'" + alias + "' (" +
|
||||
mapPBEParamsToAlgorithm(algOid, algParams) +
|
||||
" iterations: " + ic + ")");
|
||||
try {
|
||||
// Special handling required for PBE: needs a PBEKeySpec
|
||||
Key tmp;
|
||||
if (keyAlgo.startsWith("PBE")) {
|
||||
SecretKeyFactory sKeyFactory =
|
||||
SecretKeyFactory.getInstance(keyAlgo);
|
||||
KeySpec pbeKeySpec =
|
||||
sKeyFactory.getKeySpec(secretKeySpec, PBEKeySpec.class);
|
||||
try {
|
||||
tmp = sKeyFactory.generateSecret(pbeKeySpec);
|
||||
} finally {
|
||||
((PBEKeySpec)pbeKeySpec).clearPassword();
|
||||
SharedSecrets.getJavaxCryptoSpecAccess()
|
||||
.clearSecretKeySpec(secretKeySpec);
|
||||
}
|
||||
} else {
|
||||
tmp = secretKeySpec;
|
||||
}
|
||||
|
||||
if (debug != null) {
|
||||
debug.println("Retrieved a protected secret key at alias " +
|
||||
"'" + alias + "' (" +
|
||||
mapPBEParamsToAlgorithm(algOid, algParams) +
|
||||
" iterations: " + ic + ")");
|
||||
}
|
||||
return tmp;
|
||||
} finally {
|
||||
Arrays.fill(keyBytes, (byte)0);
|
||||
}
|
||||
}
|
||||
return tmp;
|
||||
} finally {
|
||||
val.clear();
|
||||
Arrays.fill(keyInfo, (byte) 0);
|
||||
}
|
||||
}, password);
|
||||
|
||||
@ -600,8 +625,15 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
|
||||
}
|
||||
|
||||
// Encrypt the private key
|
||||
keyEntry.protectedPrivKey =
|
||||
encryptPrivateKey(key.getEncoded(), passwordProtection);
|
||||
byte[] encoded = key.getEncoded();
|
||||
try {
|
||||
keyEntry.protectedPrivKey =
|
||||
encryptPrivateKey(encoded, passwordProtection);
|
||||
} finally {
|
||||
if (encoded != null) {
|
||||
Arrays.fill(encoded, (byte) 0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new KeyStoreException("Private key is not encoded" +
|
||||
"as PKCS#8");
|
||||
@ -629,17 +661,25 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
|
||||
keyEntry.date = new Date();
|
||||
|
||||
// Encode secret key in a PKCS#8
|
||||
DerOutputStream pkcs8 = new DerOutputStream();
|
||||
DerOutputStream secretKeyInfo = new DerOutputStream();
|
||||
secretKeyInfo.putInteger(0);
|
||||
AlgorithmId algId = AlgorithmId.get(key.getAlgorithm());
|
||||
algId.encode(secretKeyInfo);
|
||||
secretKeyInfo.putOctetString(key.getEncoded());
|
||||
pkcs8.write(DerValue.tag_Sequence, secretKeyInfo);
|
||||
|
||||
// Encrypt the secret key (using same PBE as for private keys)
|
||||
keyEntry.protectedSecretKey =
|
||||
encryptPrivateKey(pkcs8.toByteArray(), passwordProtection);
|
||||
byte[] encoded = key.getEncoded();
|
||||
secretKeyInfo.putOctetString(encoded);
|
||||
Arrays.fill(encoded, (byte)0);
|
||||
|
||||
DerValue pkcs8 = DerValue.wrap(DerValue.tag_Sequence, secretKeyInfo);
|
||||
byte[] p8Array = pkcs8.toByteArray();
|
||||
pkcs8.clear();
|
||||
try {
|
||||
// Encrypt the secret key (using same PBE as for private keys)
|
||||
keyEntry.protectedSecretKey =
|
||||
encryptPrivateKey(p8Array, passwordProtection);
|
||||
} finally {
|
||||
Arrays.fill(p8Array, (byte)0);
|
||||
}
|
||||
|
||||
if (debug != null) {
|
||||
debug.println("Setting a protected secret key at alias '" +
|
||||
@ -830,6 +870,17 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
|
||||
return skey;
|
||||
}
|
||||
|
||||
/*
|
||||
* Destroy the key obtained from getPBEKey().
|
||||
*/
|
||||
private void destroyPBEKey(SecretKey key) {
|
||||
try {
|
||||
key.destroy();
|
||||
} catch (DestroyFailedException e) {
|
||||
// Accept this
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Encrypt private key or secret key using Password-based encryption (PBE)
|
||||
* as defined in PKCS#5.
|
||||
@ -874,9 +925,13 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
|
||||
}
|
||||
|
||||
// Use JCE
|
||||
SecretKey skey = getPBEKey(passwordProtection.getPassword());
|
||||
Cipher cipher = Cipher.getInstance(algorithm);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, skey, algParams);
|
||||
SecretKey skey = getPBEKey(passwordProtection.getPassword());
|
||||
try {
|
||||
cipher.init(Cipher.ENCRYPT_MODE, skey, algParams);
|
||||
} finally {
|
||||
destroyPBEKey(skey);
|
||||
}
|
||||
byte[] encryptedKey = cipher.doFinal(data);
|
||||
algid = new AlgorithmId(pbeOID, cipher.getParameters());
|
||||
|
||||
@ -1462,7 +1517,11 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
|
||||
PBEParameterSpec params =
|
||||
new PBEParameterSpec(salt, macIterationCount);
|
||||
SecretKey key = getPBEKey(passwd);
|
||||
m.init(key, params);
|
||||
try {
|
||||
m.init(key, params);
|
||||
} finally {
|
||||
destroyPBEKey(key);
|
||||
}
|
||||
m.update(data);
|
||||
byte[] macResult = m.doFinal();
|
||||
|
||||
@ -1867,9 +1926,13 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
|
||||
DerOutputStream bytes = new DerOutputStream();
|
||||
|
||||
// Use JCE
|
||||
SecretKey skey = getPBEKey(password);
|
||||
Cipher cipher = Cipher.getInstance(certProtectionAlgorithm);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, skey, algParams);
|
||||
SecretKey skey = getPBEKey(password);
|
||||
try {
|
||||
cipher.init(Cipher.ENCRYPT_MODE, skey, algParams);
|
||||
} finally {
|
||||
destroyPBEKey(skey);
|
||||
}
|
||||
encryptedData = cipher.doFinal(data);
|
||||
|
||||
AlgorithmId algId = new AlgorithmId(
|
||||
@ -2075,10 +2138,14 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
|
||||
try {
|
||||
RetryWithZero.run(pass -> {
|
||||
// Use JCE
|
||||
SecretKey skey = getPBEKey(pass);
|
||||
Cipher cipher = Cipher.getInstance(
|
||||
mapPBEParamsToAlgorithm(algOid, algParams));
|
||||
cipher.init(Cipher.DECRYPT_MODE, skey, algParams);
|
||||
SecretKey skey = getPBEKey(pass);
|
||||
try {
|
||||
cipher.init(Cipher.DECRYPT_MODE, skey, algParams);
|
||||
} finally {
|
||||
destroyPBEKey(skey);
|
||||
}
|
||||
loadSafeContents(new DerInputStream(cipher.doFinal(rawData)));
|
||||
return null;
|
||||
}, password);
|
||||
@ -2128,7 +2195,11 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
|
||||
|
||||
RetryWithZero.run(pass -> {
|
||||
SecretKey key = getPBEKey(pass);
|
||||
m.init(key, params);
|
||||
try {
|
||||
m.init(key, params);
|
||||
} finally {
|
||||
destroyPBEKey(key);
|
||||
}
|
||||
m.update(authSafeData);
|
||||
byte[] macResult = m.doFinal();
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2021, 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
|
||||
@ -495,13 +495,16 @@ public class CtrDrbg extends AbstractDrbg {
|
||||
// Step 4.1. Increment
|
||||
addOne(v, ctrLen);
|
||||
try {
|
||||
// Step 4.2. Encrypt
|
||||
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(k, keyAlg));
|
||||
byte[] out = cipher.doFinal(v);
|
||||
|
||||
// Step 4.2. Encrypt
|
||||
// Step 4.3 and 5. Cat bytes and leftmost
|
||||
System.arraycopy(out, 0, result, pos,
|
||||
(len > blockLen) ? blockLen : len);
|
||||
if (len > blockLen) {
|
||||
cipher.doFinal(v, 0, blockLen, result, pos);
|
||||
} else {
|
||||
byte[] out = cipher.doFinal(v);
|
||||
System.arraycopy(out, 0, result, pos, len);
|
||||
Arrays.fill(out, (byte)0);
|
||||
}
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw new InternalError(e);
|
||||
}
|
||||
|
@ -37,6 +37,7 @@ import java.security.spec.KeySpec;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* This class implements the DSA key factory of the Sun provider.
|
||||
@ -93,7 +94,7 @@ public class DSAKeyFactory extends KeyFactorySpi {
|
||||
* is inappropriate for this key factory to produce a private key.
|
||||
*/
|
||||
protected PrivateKey engineGeneratePrivate(KeySpec keySpec)
|
||||
throws InvalidKeySpecException {
|
||||
throws InvalidKeySpecException {
|
||||
try {
|
||||
if (keySpec instanceof DSAPrivateKeySpec) {
|
||||
DSAPrivateKeySpec dsaPrivKeySpec = (DSAPrivateKeySpec)keySpec;
|
||||
@ -103,9 +104,12 @@ public class DSAKeyFactory extends KeyFactorySpi {
|
||||
dsaPrivKeySpec.getG());
|
||||
|
||||
} else if (keySpec instanceof PKCS8EncodedKeySpec) {
|
||||
return new DSAPrivateKey
|
||||
(((PKCS8EncodedKeySpec)keySpec).getEncoded());
|
||||
|
||||
byte[] encoded = ((PKCS8EncodedKeySpec)keySpec).getEncoded();
|
||||
try {
|
||||
return new DSAPrivateKey(encoded);
|
||||
} finally {
|
||||
Arrays.fill(encoded, (byte) 0);
|
||||
}
|
||||
} else {
|
||||
throw new InvalidKeySpecException
|
||||
("Inappropriate key specification");
|
||||
@ -183,8 +187,12 @@ public class DSAKeyFactory extends KeyFactorySpi {
|
||||
params.getG()));
|
||||
|
||||
} else if (keySpec.isAssignableFrom(pkcs8KeySpec)) {
|
||||
return keySpec.cast(new PKCS8EncodedKeySpec(key.getEncoded()));
|
||||
|
||||
byte[] encoded = key.getEncoded();
|
||||
try {
|
||||
return keySpec.cast(new PKCS8EncodedKeySpec(encoded));
|
||||
} finally {
|
||||
Arrays.fill(encoded, (byte)0);
|
||||
}
|
||||
} else {
|
||||
throw new InvalidKeySpecException
|
||||
("Inappropriate key specification");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 2021, 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
|
||||
@ -32,6 +32,7 @@ import java.security.AlgorithmParameters;
|
||||
import java.security.spec.DSAParameterSpec;
|
||||
import java.security.spec.InvalidParameterSpecException;
|
||||
import java.security.interfaces.DSAParams;
|
||||
import java.util.Arrays;
|
||||
|
||||
import sun.security.x509.AlgIdDSA;
|
||||
import sun.security.pkcs.PKCS8Key;
|
||||
@ -68,8 +69,11 @@ public final class DSAPrivateKey extends PKCS8Key
|
||||
algid = new AlgIdDSA(p, q, g);
|
||||
|
||||
try {
|
||||
key = new DerValue(DerValue.tag_Integer,
|
||||
x.toByteArray()).toByteArray();
|
||||
byte[] xbytes = x.toByteArray();
|
||||
DerValue val = new DerValue(DerValue.tag_Integer, xbytes);
|
||||
key = val.toByteArray();
|
||||
val.clear();
|
||||
Arrays.fill(xbytes, (byte)0);
|
||||
} catch (IOException e) {
|
||||
throw new AssertionError("Should not happen", e);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2021, 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
|
||||
@ -254,15 +254,15 @@ public class HashDrbg extends AbstractHashDrbg {
|
||||
int len = output.length;
|
||||
|
||||
while (len > 0) {
|
||||
// Step 4.1 w = Hash (data).
|
||||
digest.update(data);
|
||||
if (len < outLen) {
|
||||
// Step 4.1 w = Hash (data).
|
||||
// Step 4.2 W = W || w.
|
||||
System.arraycopy(digest.digest(data), 0, output, pos,
|
||||
len);
|
||||
byte[] out = digest.digest();
|
||||
System.arraycopy(out, 0, output, pos, len);
|
||||
Arrays.fill(out, (byte)0);
|
||||
} else {
|
||||
try {
|
||||
// Step 4.1 w = Hash (data).
|
||||
digest.update(data);
|
||||
// Step 4.2 digest into right position, no need to cat
|
||||
digest.digest(output, pos, outLen);
|
||||
} catch (DigestException e) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2021, 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
|
||||
@ -206,6 +206,7 @@ final class KeyProtector {
|
||||
digest = md.digest();
|
||||
md.reset();
|
||||
System.arraycopy(digest, 0, encrKey, encrKeyOffset, digest.length);
|
||||
Arrays.fill(plainKey, (byte)0);
|
||||
|
||||
// wrap the protected private key in a PKCS#8-style
|
||||
// EncryptedPrivateKeyInfo, and returns its encoding
|
||||
@ -308,9 +309,11 @@ final class KeyProtector {
|
||||
// algorithm and instantiates the appropriate key factory,
|
||||
// which in turn parses the key material.
|
||||
try {
|
||||
return PKCS8Key.parseKey(new DerValue(plainKey));
|
||||
return PKCS8Key.parseKey(plainKey);
|
||||
} catch (IOException ioe) {
|
||||
throw new UnrecoverableKeyException(ioe.getMessage());
|
||||
} finally {
|
||||
Arrays.fill(plainKey, (byte)0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2021, 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
|
||||
@ -42,4 +42,8 @@ public final class SHAKE256 extends SHA3 {
|
||||
public byte[] digest() {
|
||||
return engineDigest();
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
engineReset();
|
||||
}
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ import java.math.BigInteger;
|
||||
import java.security.*;
|
||||
import java.security.interfaces.*;
|
||||
import java.security.spec.*;
|
||||
import java.util.Arrays;
|
||||
|
||||
import sun.security.action.GetPropertyAction;
|
||||
import sun.security.rsa.RSAUtil.KeyType;
|
||||
@ -308,8 +309,14 @@ public class RSAKeyFactory extends KeyFactorySpi {
|
||||
throw new InvalidKeyException("Invalid key", e);
|
||||
}
|
||||
} else {
|
||||
return RSAPrivateCrtKeyImpl.newKey(type, key.getFormat(),
|
||||
key.getEncoded());
|
||||
byte[] encoded = key.getEncoded();
|
||||
try {
|
||||
return RSAPrivateCrtKeyImpl.newKey(type, key.getFormat(), encoded);
|
||||
} finally {
|
||||
if (encoded != null) {
|
||||
Arrays.fill(encoded, (byte)0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -340,8 +347,12 @@ public class RSAKeyFactory extends KeyFactorySpi {
|
||||
private PrivateKey generatePrivate(KeySpec keySpec)
|
||||
throws GeneralSecurityException {
|
||||
if (keySpec instanceof PKCS8EncodedKeySpec) {
|
||||
return RSAPrivateCrtKeyImpl.newKey(type, "PKCS#8",
|
||||
((PKCS8EncodedKeySpec)keySpec).getEncoded());
|
||||
byte[] encoded = ((PKCS8EncodedKeySpec)keySpec).getEncoded();
|
||||
try {
|
||||
return RSAPrivateCrtKeyImpl.newKey(type, "PKCS#8", encoded);
|
||||
} finally {
|
||||
Arrays.fill(encoded, (byte)0);
|
||||
}
|
||||
} else if (keySpec instanceof RSAPrivateCrtKeySpec) {
|
||||
RSAPrivateCrtKeySpec rsaSpec = (RSAPrivateCrtKeySpec)keySpec;
|
||||
try {
|
||||
@ -404,7 +415,12 @@ public class RSAKeyFactory extends KeyFactorySpi {
|
||||
}
|
||||
} else if (key instanceof RSAPrivateKey) {
|
||||
if (keySpec.isAssignableFrom(PKCS8_KEYSPEC_CLS)) {
|
||||
return keySpec.cast(new PKCS8EncodedKeySpec(key.getEncoded()));
|
||||
byte[] encoded = key.getEncoded();
|
||||
try {
|
||||
return keySpec.cast(new PKCS8EncodedKeySpec(encoded));
|
||||
} finally {
|
||||
Arrays.fill(encoded, (byte)0);
|
||||
}
|
||||
} else if (keySpec.isAssignableFrom(RSA_PRIVCRT_KEYSPEC_CLS)) {
|
||||
// All supported keyspecs (other than PKCS8_KEYSPEC_CLS) descend from RSA_PRIVCRT_KEYSPEC_CLS
|
||||
if (key instanceof RSAPrivateCrtKey) {
|
||||
|
@ -31,6 +31,7 @@ import java.math.BigInteger;
|
||||
import java.security.*;
|
||||
import java.security.spec.*;
|
||||
import java.security.interfaces.*;
|
||||
import java.util.Arrays;
|
||||
|
||||
import sun.security.util.*;
|
||||
|
||||
@ -192,20 +193,44 @@ public final class RSAPrivateCrtKeyImpl
|
||||
this.keyParams = keyParams;
|
||||
|
||||
try {
|
||||
// generate the key encoding
|
||||
DerOutputStream out = new DerOutputStream();
|
||||
byte[][] nbytes = new byte[8][];
|
||||
nbytes[0] = n.toByteArray();
|
||||
nbytes[1] = e.toByteArray();
|
||||
nbytes[2] = d.toByteArray();
|
||||
nbytes[3] = p.toByteArray();
|
||||
nbytes[4] = q.toByteArray();
|
||||
nbytes[5] = pe.toByteArray();
|
||||
nbytes[6] = qe.toByteArray();
|
||||
nbytes[7] = coeff.toByteArray();
|
||||
|
||||
// Initiate with a big enough size so there's no need to
|
||||
// reallocate memory later and thus can be cleaned up
|
||||
// reliably.
|
||||
DerOutputStream out = new DerOutputStream(
|
||||
nbytes[0].length + nbytes[1].length +
|
||||
nbytes[2].length + nbytes[3].length +
|
||||
nbytes[4].length + nbytes[5].length +
|
||||
nbytes[6].length + nbytes[7].length +
|
||||
100); // Enough for version(3) and 8 tag+length(3 or 4)
|
||||
out.putInteger(0); // version must be 0
|
||||
out.putInteger(n);
|
||||
out.putInteger(e);
|
||||
out.putInteger(d);
|
||||
out.putInteger(p);
|
||||
out.putInteger(q);
|
||||
out.putInteger(pe);
|
||||
out.putInteger(qe);
|
||||
out.putInteger(coeff);
|
||||
DerValue val =
|
||||
new DerValue(DerValue.tag_Sequence, out.toByteArray());
|
||||
out.putInteger(nbytes[0]);
|
||||
out.putInteger(nbytes[1]);
|
||||
out.putInteger(nbytes[2]);
|
||||
out.putInteger(nbytes[3]);
|
||||
out.putInteger(nbytes[4]);
|
||||
out.putInteger(nbytes[5]);
|
||||
out.putInteger(nbytes[6]);
|
||||
out.putInteger(nbytes[7]);
|
||||
// Private values from [2] on.
|
||||
Arrays.fill(nbytes[2], (byte)0);
|
||||
Arrays.fill(nbytes[3], (byte)0);
|
||||
Arrays.fill(nbytes[4], (byte)0);
|
||||
Arrays.fill(nbytes[5], (byte)0);
|
||||
Arrays.fill(nbytes[6], (byte)0);
|
||||
Arrays.fill(nbytes[7], (byte)0);
|
||||
DerValue val = DerValue.wrap(DerValue.tag_Sequence, out);
|
||||
key = val.toByteArray();
|
||||
val.clear();
|
||||
} catch (IOException exc) {
|
||||
// should never occur
|
||||
throw new InvalidKeyException(exc);
|
||||
@ -285,29 +310,33 @@ public final class RSAPrivateCrtKeyImpl
|
||||
// e, d, p, q, pe, qe, and coeff, and return the parsed components.
|
||||
private static BigInteger[] parseASN1(byte[] raw) throws IOException {
|
||||
DerValue derValue = new DerValue(raw);
|
||||
if (derValue.tag != DerValue.tag_Sequence) {
|
||||
throw new IOException("Not a SEQUENCE");
|
||||
}
|
||||
int version = derValue.data.getInteger();
|
||||
if (version != 0) {
|
||||
throw new IOException("Version must be 0");
|
||||
}
|
||||
try {
|
||||
if (derValue.tag != DerValue.tag_Sequence) {
|
||||
throw new IOException("Not a SEQUENCE");
|
||||
}
|
||||
int version = derValue.data.getInteger();
|
||||
if (version != 0) {
|
||||
throw new IOException("Version must be 0");
|
||||
}
|
||||
|
||||
BigInteger[] result = new BigInteger[8]; // n, e, d, p, q, pe, qe, coeff
|
||||
/*
|
||||
* Some implementations do not correctly encode ASN.1 INTEGER values
|
||||
* in 2's complement format, resulting in a negative integer when
|
||||
* decoded. Correct the error by converting it to a positive integer.
|
||||
*
|
||||
* See CR 6255949
|
||||
*/
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
result[i] = derValue.data.getPositiveBigInteger();
|
||||
BigInteger[] result = new BigInteger[8]; // n, e, d, p, q, pe, qe, coeff
|
||||
/*
|
||||
* Some implementations do not correctly encode ASN.1 INTEGER values
|
||||
* in 2's complement format, resulting in a negative integer when
|
||||
* decoded. Correct the error by converting it to a positive integer.
|
||||
*
|
||||
* See CR 6255949
|
||||
*/
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
result[i] = derValue.data.getPositiveBigInteger();
|
||||
}
|
||||
if (derValue.data.available() != 0) {
|
||||
throw new IOException("Extra data available");
|
||||
}
|
||||
return result;
|
||||
} finally {
|
||||
derValue.clear();
|
||||
}
|
||||
if (derValue.data.available() != 0) {
|
||||
throw new IOException("Extra data available");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void parseKeyBits() throws InvalidKeyException {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2021, 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,7 @@ import java.math.BigInteger;
|
||||
import java.security.*;
|
||||
import java.security.spec.AlgorithmParameterSpec;
|
||||
import java.security.interfaces.*;
|
||||
import java.util.Arrays;
|
||||
|
||||
import sun.security.util.*;
|
||||
import sun.security.pkcs.PKCS8Key;
|
||||
@ -90,19 +91,25 @@ public final class RSAPrivateKeyImpl extends PKCS8Key implements RSAPrivateKey {
|
||||
|
||||
try {
|
||||
// generate the key encoding
|
||||
DerOutputStream out = new DerOutputStream();
|
||||
byte[] nbytes = n.toByteArray();
|
||||
byte[] dbytes = d.toByteArray();
|
||||
DerOutputStream out = new DerOutputStream(
|
||||
nbytes.length + dbytes.length + 50);
|
||||
// Enough for 7 zeroes (21) and 2 tag+length(4)
|
||||
out.putInteger(0); // version must be 0
|
||||
out.putInteger(n);
|
||||
out.putInteger(nbytes);
|
||||
Arrays.fill(nbytes, (byte)0);
|
||||
out.putInteger(0);
|
||||
out.putInteger(d);
|
||||
out.putInteger(dbytes);
|
||||
Arrays.fill(dbytes, (byte)0);
|
||||
out.putInteger(0);
|
||||
out.putInteger(0);
|
||||
out.putInteger(0);
|
||||
out.putInteger(0);
|
||||
out.putInteger(0);
|
||||
DerValue val =
|
||||
new DerValue(DerValue.tag_Sequence, out.toByteArray());
|
||||
DerValue val = DerValue.wrap(DerValue.tag_Sequence, out);
|
||||
key = val.toByteArray();
|
||||
val.clear();
|
||||
} catch (IOException exc) {
|
||||
// should never occur
|
||||
throw new InvalidKeyException(exc);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 2021, 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
|
||||
@ -169,6 +169,17 @@ extends ByteArrayOutputStream implements DerEncoder {
|
||||
write(buf, 0, buf.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Marshals a DER integer on the output stream.
|
||||
*
|
||||
* @param i the integer in bytes, equivalent to BigInteger::toByteArray.
|
||||
*/
|
||||
public void putInteger(byte[] buf) throws IOException {
|
||||
write(DerValue.tag_Integer);
|
||||
putLength(buf.length);
|
||||
write(buf, 0, buf.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Marshals a DER integer on the output stream.
|
||||
* @param i the integer in the form of an Integer.
|
||||
@ -575,4 +586,8 @@ extends ByteArrayOutputStream implements DerEncoder {
|
||||
public void derEncode(OutputStream out) throws IOException {
|
||||
out.write(toByteArray());
|
||||
}
|
||||
|
||||
byte[] buf() {
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
|
@ -286,6 +286,22 @@ public class DerValue {
|
||||
this(tag, buffer.clone(), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps an DerOutputStream. All bytes currently written
|
||||
* into the stream will become the content of the newly
|
||||
* created DerValue.
|
||||
*
|
||||
* Attention: do not reset the DerOutputStream after this call.
|
||||
* No array copying is made.
|
||||
*
|
||||
* @param tag the tag
|
||||
* @param out the DerOutputStream
|
||||
* @returns a new DerValue using out as its content
|
||||
*/
|
||||
public static DerValue wrap(byte tag, DerOutputStream out) {
|
||||
return new DerValue(tag, out.buf(), 0, out.size(), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse an ASN.1/BER encoded datum. The entire encoding must hold exactly
|
||||
* one datum, including its tag and length.
|
||||
@ -1072,10 +1088,15 @@ public class DerValue {
|
||||
* @return DER-encoded value, including tag and length.
|
||||
*/
|
||||
public byte[] toByteArray() throws IOException {
|
||||
data.pos = data.start; // Compatibility. At head.
|
||||
// Minimize content duplication by writing out tag and length only
|
||||
DerOutputStream out = new DerOutputStream();
|
||||
encode(out);
|
||||
data.pos = data.start; // encode go last, should go back
|
||||
return out.toByteArray();
|
||||
out.write(tag);
|
||||
out.putLength(end - start);
|
||||
int headLen = out.size();
|
||||
byte[] result = Arrays.copyOf(out.buf(), end - start + headLen);
|
||||
System.arraycopy(buffer, start, result, headLen, end - start);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1216,4 +1237,8 @@ public class DerValue {
|
||||
}
|
||||
return result.toArray(new DerValue[0]);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
Arrays.fill(buffer, start, end, (byte)0);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2006, 2021, 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 sun.security.util;
|
||||
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.security.*;
|
||||
@ -122,8 +124,11 @@ public final class ECUtil {
|
||||
throws InvalidKeySpecException {
|
||||
KeyFactory keyFactory = getKeyFactory();
|
||||
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);
|
||||
|
||||
return (ECPrivateKey)keyFactory.generatePrivate(keySpec);
|
||||
try {
|
||||
return (ECPrivateKey) keyFactory.generatePrivate(keySpec);
|
||||
} finally {
|
||||
SharedSecrets.getJavaSecuritySpecAccess().clearEncodedKeySpec(keySpec);
|
||||
}
|
||||
}
|
||||
|
||||
public static ECPrivateKey generateECPrivateKey(BigInteger s,
|
||||
|
@ -47,6 +47,7 @@ import javax.crypto.spec.DHParameterSpec;
|
||||
import javax.crypto.spec.DHPublicKeySpec;
|
||||
import java.math.BigInteger;
|
||||
import java.security.spec.NamedParameterSpec;
|
||||
import java.util.Arrays;
|
||||
|
||||
import sun.security.jca.JCAUtil;
|
||||
|
||||
@ -82,8 +83,12 @@ public final class KeyUtil {
|
||||
if (key instanceof SecretKey) {
|
||||
SecretKey sk = (SecretKey)key;
|
||||
String format = sk.getFormat();
|
||||
if ("RAW".equals(format) && sk.getEncoded() != null) {
|
||||
size = (sk.getEncoded().length * 8);
|
||||
if ("RAW".equals(format)) {
|
||||
byte[] encoded = sk.getEncoded();
|
||||
if (encoded != null) {
|
||||
size = (encoded.length * 8);
|
||||
Arrays.fill(encoded, (byte)0);
|
||||
}
|
||||
} // Otherwise, it may be a unextractable key of PKCS#11, or
|
||||
// a key we are not able to handle.
|
||||
} else if (key instanceof RSAKey) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 2021, 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
|
||||
@ -100,32 +100,6 @@ class AlgIdDSA extends AlgorithmId implements DSAParams
|
||||
@Deprecated
|
||||
public AlgIdDSA () {}
|
||||
|
||||
AlgIdDSA (DerValue val) throws IOException
|
||||
{ super(val.getOID()); }
|
||||
|
||||
/**
|
||||
* Construct an AlgIdDSA from an X.509 encoded byte array.
|
||||
*/
|
||||
public AlgIdDSA (byte[] encodedAlg) throws IOException
|
||||
{ super (new DerValue(encodedAlg).getOID()); }
|
||||
|
||||
/**
|
||||
* Constructs a DSS/DSA Algorithm ID from unsigned integers that
|
||||
* define the algorithm parameters. Those integers are encoded
|
||||
* as big-endian byte arrays.
|
||||
*
|
||||
* @param p the DSS/DSA parameter "P"
|
||||
* @param q the DSS/DSA parameter "Q"
|
||||
* @param g the DSS/DSA parameter "G"
|
||||
*/
|
||||
public AlgIdDSA (byte[] p, byte[] q, byte[] g)
|
||||
throws IOException
|
||||
{
|
||||
this (new BigInteger (1, p),
|
||||
new BigInteger (1, q),
|
||||
new BigInteger (1, g));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a DSS/DSA Algorithm ID from numeric parameters.
|
||||
* If all three are null, then the parameters portion of the algorithm id
|
||||
@ -135,8 +109,7 @@ class AlgIdDSA extends AlgorithmId implements DSAParams
|
||||
* @param q the DSS/DSA parameter "Q"
|
||||
* @param g the DSS/DSA parameter "G"
|
||||
*/
|
||||
public AlgIdDSA (BigInteger p, BigInteger q, BigInteger g)
|
||||
{
|
||||
public AlgIdDSA (BigInteger p, BigInteger q, BigInteger g) {
|
||||
super (DSA_oid);
|
||||
|
||||
if (p != null || q != null || g != null) {
|
||||
@ -168,28 +141,29 @@ class AlgIdDSA extends AlgorithmId implements DSAParams
|
||||
* For algorithm IDs which haven't been created from a DER encoded
|
||||
* value, "params" must be created.
|
||||
*/
|
||||
private void initializeParams ()
|
||||
throws IOException
|
||||
{
|
||||
DerOutputStream out = new DerOutputStream ();
|
||||
|
||||
private void initializeParams () throws IOException {
|
||||
DerOutputStream out = new DerOutputStream();
|
||||
out.putInteger(p);
|
||||
out.putInteger(q);
|
||||
out.putInteger(g);
|
||||
params = new DerValue (DerValue.tag_Sequence,out.toByteArray ());
|
||||
DerOutputStream result = new DerOutputStream();
|
||||
result.write(DerValue.tag_Sequence, out);
|
||||
encodedParams = result.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses algorithm parameters P, Q, and G. They're found
|
||||
* in the "params" member, which never needs to be changed.
|
||||
*/
|
||||
protected void decodeParams ()
|
||||
throws IOException
|
||||
{
|
||||
if (params == null)
|
||||
protected void decodeParams () throws IOException {
|
||||
if (encodedParams == null) {
|
||||
throw new IOException("DSA alg params are null");
|
||||
if (params.tag != DerValue.tag_Sequence)
|
||||
throw new IOException("DSA alg parsing error");
|
||||
}
|
||||
|
||||
DerValue params = new DerValue(encodedParams);
|
||||
if (params.tag != DerValue.tag_Sequence) {
|
||||
throw new IOException("DSA alg parsing error");
|
||||
}
|
||||
|
||||
params.data.reset ();
|
||||
|
||||
@ -206,21 +180,21 @@ class AlgIdDSA extends AlgorithmId implements DSAParams
|
||||
/*
|
||||
* Returns a formatted string describing the parameters.
|
||||
*/
|
||||
public String toString ()
|
||||
{ return paramsToString (); }
|
||||
public String toString () {
|
||||
return paramsToString();
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a string describing the parameters.
|
||||
*/
|
||||
protected String paramsToString ()
|
||||
{
|
||||
if (params == null)
|
||||
protected String paramsToString () {
|
||||
if (encodedParams == null) {
|
||||
return " null\n";
|
||||
else
|
||||
return
|
||||
"\n p:\n" + Debug.toHexString(p) +
|
||||
"\n q:\n" + Debug.toHexString(q) +
|
||||
"\n g:\n" + Debug.toHexString(g) +
|
||||
"\n";
|
||||
} else {
|
||||
return "\n p:\n" + Debug.toHexString(p) +
|
||||
"\n q:\n" + Debug.toHexString(q) +
|
||||
"\n g:\n" + Debug.toHexString(g) +
|
||||
"\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -70,17 +70,13 @@ public class AlgorithmId implements Serializable, DerEncoder {
|
||||
// The (parsed) parameters
|
||||
@SuppressWarnings("serial") // Not statically typed as Serializable
|
||||
private AlgorithmParameters algParams;
|
||||
private boolean constructedFromDer = true;
|
||||
|
||||
/**
|
||||
* Parameters for this algorithm. These are stored in unparsed
|
||||
* DER-encoded form; subclasses can be made to automaticaly parse
|
||||
* them so there is fast access to these parameters.
|
||||
*/
|
||||
@SuppressWarnings("serial") // Not statically typed as Serializable
|
||||
protected DerValue params;
|
||||
|
||||
private transient byte[] encodedParams;
|
||||
protected transient byte[] encodedParams;
|
||||
|
||||
/**
|
||||
* Constructs an algorithm ID which will be initialized
|
||||
@ -107,17 +103,14 @@ public class AlgorithmId implements Serializable, DerEncoder {
|
||||
*/
|
||||
public AlgorithmId(ObjectIdentifier oid, AlgorithmParameters algparams) {
|
||||
algid = oid;
|
||||
algParams = algparams;
|
||||
constructedFromDer = false;
|
||||
this.algParams = algparams;
|
||||
if (algParams != null) {
|
||||
try {
|
||||
encodedParams = algParams.getEncoded();
|
||||
} catch (IOException ioe) {
|
||||
// It should be safe to ignore this.
|
||||
// This exception can occur if AlgorithmParameters was not
|
||||
// initialized (which should not occur), or if it was
|
||||
// initialized with bogus parameters, which should have
|
||||
// been detected when init was called.
|
||||
// Ignore this at the moment. This exception can occur
|
||||
// if AlgorithmParameters was not initialized yet. Will
|
||||
// try to re-getEncoded() again later.
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -131,8 +124,7 @@ public class AlgorithmId implements Serializable, DerEncoder {
|
||||
public AlgorithmId(ObjectIdentifier oid, DerValue params)
|
||||
throws IOException {
|
||||
this.algid = oid;
|
||||
this.params = params;
|
||||
if (this.params != null) {
|
||||
if (params != null) {
|
||||
encodedParams = params.toByteArray();
|
||||
decodeParams();
|
||||
}
|
||||
@ -177,20 +169,14 @@ public class AlgorithmId implements Serializable, DerEncoder {
|
||||
DerOutputStream tmp = new DerOutputStream();
|
||||
|
||||
bytes.putOID(algid);
|
||||
// Setup params from algParams since no DER encoding is given
|
||||
if (constructedFromDer == false) {
|
||||
if (algParams != null) {
|
||||
if (encodedParams == null) {
|
||||
// call getEncoded again in case algParams were initialized
|
||||
// after being passed in to ctor.
|
||||
encodedParams = algParams.getEncoded();
|
||||
}
|
||||
params = new DerValue(encodedParams);
|
||||
} else {
|
||||
params = null;
|
||||
}
|
||||
|
||||
// Re-getEncoded() from algParams if it was not initialized
|
||||
if (algParams != null && encodedParams == null) {
|
||||
encodedParams = algParams.getEncoded();
|
||||
// If still not initialized. Let the IOE be thrown.
|
||||
}
|
||||
if (params == null) {
|
||||
|
||||
if (encodedParams == null) {
|
||||
// Changes backed out for compatibility with Solaris
|
||||
|
||||
// Several AlgorithmId should omit the whole parameter part when
|
||||
@ -242,7 +228,7 @@ public class AlgorithmId implements Serializable, DerEncoder {
|
||||
bytes.putNull();
|
||||
}
|
||||
} else {
|
||||
bytes.putDerValue(params);
|
||||
bytes.write(encodedParams);
|
||||
}
|
||||
tmp.write(DerValue.tag_Sequence, bytes);
|
||||
out.write(tmp.toByteArray());
|
||||
@ -285,7 +271,7 @@ public class AlgorithmId implements Serializable, DerEncoder {
|
||||
// first check the list of support oids
|
||||
KnownOIDs o = KnownOIDs.findMatch(oidStr);
|
||||
if (o == KnownOIDs.SpecifiedSHA2withECDSA) {
|
||||
if (params != null) {
|
||||
if (encodedParams != null) {
|
||||
try {
|
||||
AlgorithmId digestParams =
|
||||
AlgorithmId.parse(new DerValue(encodedParams));
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2021, 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
|
||||
@ -228,7 +228,7 @@ abstract class P11Key implements Key, Length {
|
||||
throw new NotSerializableException
|
||||
("Cannot serialize sensitive and unextractable keys");
|
||||
}
|
||||
return new KeyRep(type, getAlgorithm(), format, getEncoded());
|
||||
return new KeyRep(type, getAlgorithm(), format, getEncodedInternal());
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
|
@ -28,6 +28,7 @@ package sun.security.ec;
|
||||
import java.security.*;
|
||||
import java.security.interfaces.*;
|
||||
import java.security.spec.*;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* KeyFactory for EC keys. Keys must be instances of PublicKey or PrivateKey
|
||||
@ -204,7 +205,12 @@ public final class ECKeyFactory extends KeyFactorySpi {
|
||||
ecKey.getParams()
|
||||
);
|
||||
} else if ("PKCS#8".equals(key.getFormat())) {
|
||||
return new ECPrivateKeyImpl(key.getEncoded());
|
||||
byte[] encoded = key.getEncoded();
|
||||
try {
|
||||
return new ECPrivateKeyImpl(encoded);
|
||||
} finally {
|
||||
Arrays.fill(encoded, (byte)0);
|
||||
}
|
||||
} else {
|
||||
throw new InvalidKeyException("Private keys must be instance "
|
||||
+ "of ECPrivateKey or have PKCS#8 encoding");
|
||||
@ -234,7 +240,12 @@ public final class ECKeyFactory extends KeyFactorySpi {
|
||||
throws GeneralSecurityException {
|
||||
if (keySpec instanceof PKCS8EncodedKeySpec) {
|
||||
PKCS8EncodedKeySpec pkcsSpec = (PKCS8EncodedKeySpec)keySpec;
|
||||
return new ECPrivateKeyImpl(pkcsSpec.getEncoded());
|
||||
byte[] encoded = pkcsSpec.getEncoded();
|
||||
try {
|
||||
return new ECPrivateKeyImpl(encoded);
|
||||
} finally {
|
||||
Arrays.fill(encoded, (byte) 0);
|
||||
}
|
||||
} else if (keySpec instanceof ECPrivateKeySpec) {
|
||||
ECPrivateKeySpec ecSpec = (ECPrivateKeySpec)keySpec;
|
||||
return new ECPrivateKeyImpl(ecSpec.getS(), ecSpec.getParams());
|
||||
@ -270,7 +281,12 @@ public final class ECKeyFactory extends KeyFactorySpi {
|
||||
}
|
||||
} else if (key instanceof ECPrivateKey) {
|
||||
if (keySpec.isAssignableFrom(PKCS8EncodedKeySpec.class)) {
|
||||
return keySpec.cast(new PKCS8EncodedKeySpec(key.getEncoded()));
|
||||
byte[] encoded = key.getEncoded();
|
||||
try {
|
||||
return keySpec.cast(new PKCS8EncodedKeySpec(encoded));
|
||||
} finally {
|
||||
Arrays.fill(encoded, (byte)0);
|
||||
}
|
||||
} else if (keySpec.isAssignableFrom(ECPrivateKeySpec.class)) {
|
||||
ECPrivateKey ecKey = (ECPrivateKey)key;
|
||||
return keySpec.cast(new ECPrivateKeySpec(
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2009, 2021, 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
|
||||
@ -33,6 +33,7 @@ import java.security.spec.ECGenParameterSpec;
|
||||
import java.security.spec.ECParameterSpec;
|
||||
import java.security.spec.ECPoint;
|
||||
import java.security.spec.InvalidParameterSpecException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
|
||||
import sun.security.jca.JCAUtil;
|
||||
@ -200,6 +201,7 @@ public final class ECKeyPairGenerator extends KeyPairGeneratorSpi {
|
||||
AffinePoint affPub = pub.asAffine();
|
||||
|
||||
PrivateKey privateKey = new ECPrivateKeyImpl(privArr, ecParams);
|
||||
Arrays.fill(privArr, (byte)0);
|
||||
|
||||
ECPoint w = new ECPoint(affPub.getX().asBigInteger(),
|
||||
affPub.getY().asBigInteger());
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2006, 2021, 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,7 @@ import java.math.BigInteger;
|
||||
import java.security.*;
|
||||
import java.security.interfaces.*;
|
||||
import java.security.spec.*;
|
||||
import java.util.Arrays;
|
||||
|
||||
import sun.security.util.*;
|
||||
import sun.security.x509.AlgorithmId;
|
||||
@ -103,9 +104,10 @@ public final class ECPrivateKeyImpl extends PKCS8Key implements ECPrivateKey {
|
||||
byte[] privBytes = s.clone();
|
||||
ArrayUtil.reverse(privBytes);
|
||||
out.putOctetString(privBytes);
|
||||
DerValue val =
|
||||
new DerValue(DerValue.tag_Sequence, out.toByteArray());
|
||||
Arrays.fill(privBytes, (byte)0);
|
||||
DerValue val = DerValue.wrap(DerValue.tag_Sequence, out);
|
||||
key = val.toByteArray();
|
||||
val.clear();
|
||||
} catch (IOException exc) {
|
||||
// should never occur
|
||||
throw new InvalidKeyException(exc);
|
||||
@ -124,13 +126,15 @@ public final class ECPrivateKeyImpl extends PKCS8Key implements ECPrivateKey {
|
||||
int outPos = Math.max(sOctets.length - sArr.length, 0);
|
||||
int length = Math.min(sArr.length, sOctets.length);
|
||||
System.arraycopy(sArr, inPos, sOctets, outPos, length);
|
||||
Arrays.fill(sArr, (byte)0);
|
||||
|
||||
DerOutputStream out = new DerOutputStream();
|
||||
out.putInteger(1); // version 1
|
||||
out.putOctetString(sOctets);
|
||||
DerValue val =
|
||||
new DerValue(DerValue.tag_Sequence, out.toByteArray());
|
||||
Arrays.fill(sOctets, (byte)0);
|
||||
DerValue val = DerValue.wrap(DerValue.tag_Sequence, out);
|
||||
key = val.toByteArray();
|
||||
val.clear();
|
||||
} catch (IOException exc) {
|
||||
throw new AssertionError("Should not happen", exc);
|
||||
}
|
||||
@ -147,6 +151,7 @@ public final class ECPrivateKeyImpl extends PKCS8Key implements ECPrivateKey {
|
||||
byte[] arrCopy = arrayS.clone();
|
||||
ArrayUtil.reverse(arrCopy);
|
||||
s = new BigInteger(1, arrCopy);
|
||||
Arrays.fill(arrCopy, (byte)0);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
@ -42,6 +42,7 @@ import java.security.spec.PKCS8EncodedKeySpec;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
import java.security.spec.XECPublicKeySpec;
|
||||
import java.security.spec.XECPrivateKeySpec;
|
||||
import java.util.Arrays;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class XDHKeyFactory extends KeyFactorySpi {
|
||||
@ -87,9 +88,14 @@ public class XDHKeyFactory extends KeyFactorySpi {
|
||||
return result;
|
||||
} else if (key instanceof PrivateKey &&
|
||||
key.getFormat().equals("PKCS#8")) {
|
||||
XDHPrivateKeyImpl result = new XDHPrivateKeyImpl(key.getEncoded());
|
||||
checkLockedParams(InvalidKeyException::new, result.getParams());
|
||||
return result;
|
||||
byte[] encoded = key.getEncoded();
|
||||
try {
|
||||
XDHPrivateKeyImpl result = new XDHPrivateKeyImpl(encoded);
|
||||
checkLockedParams(InvalidKeyException::new, result.getParams());
|
||||
return result;
|
||||
} finally {
|
||||
Arrays.fill(encoded, (byte)0);
|
||||
}
|
||||
} else {
|
||||
throw new InvalidKeyException("Unsupported key type or format");
|
||||
}
|
||||
@ -165,17 +171,26 @@ public class XDHKeyFactory extends KeyFactorySpi {
|
||||
|
||||
if (keySpec instanceof PKCS8EncodedKeySpec) {
|
||||
PKCS8EncodedKeySpec pkcsSpec = (PKCS8EncodedKeySpec) keySpec;
|
||||
XDHPrivateKeyImpl result =
|
||||
new XDHPrivateKeyImpl(pkcsSpec.getEncoded());
|
||||
checkLockedParams(InvalidKeySpecException::new,
|
||||
result.getParams());
|
||||
return result;
|
||||
byte[] encoded = pkcsSpec.getEncoded();
|
||||
try {
|
||||
XDHPrivateKeyImpl result = new XDHPrivateKeyImpl(encoded);
|
||||
checkLockedParams(InvalidKeySpecException::new,
|
||||
result.getParams());
|
||||
return result;
|
||||
} finally {
|
||||
Arrays.fill(encoded, (byte) 0);
|
||||
}
|
||||
} else if (keySpec instanceof XECPrivateKeySpec) {
|
||||
XECPrivateKeySpec privateKeySpec = (XECPrivateKeySpec) keySpec;
|
||||
XECParameters params = XECParameters.get(
|
||||
InvalidKeySpecException::new, privateKeySpec.getParams());
|
||||
checkLockedParams(InvalidKeySpecException::new, params);
|
||||
return new XDHPrivateKeyImpl(params, privateKeySpec.getScalar());
|
||||
byte[] scalar = privateKeySpec.getScalar();
|
||||
try {
|
||||
return new XDHPrivateKeyImpl(params, scalar);
|
||||
} finally {
|
||||
Arrays.fill(scalar, (byte)0);
|
||||
}
|
||||
} else {
|
||||
throw new InvalidKeySpecException(
|
||||
"Only PKCS8EncodedKeySpec and XECPrivateKeySpec supported");
|
||||
@ -210,14 +225,23 @@ public class XDHKeyFactory extends KeyFactorySpi {
|
||||
if (!key.getFormat().equals("PKCS#8")) {
|
||||
throw new InvalidKeySpecException("Format is not PKCS#8");
|
||||
}
|
||||
return keySpec.cast(new PKCS8EncodedKeySpec(key.getEncoded()));
|
||||
byte[] encoded = key.getEncoded();
|
||||
try {
|
||||
return keySpec.cast(new PKCS8EncodedKeySpec(encoded));
|
||||
} finally {
|
||||
Arrays.fill(encoded, (byte)0);
|
||||
}
|
||||
} else if (keySpec.isAssignableFrom(XECPrivateKeySpec.class)) {
|
||||
XECPrivateKey xecKey = (XECPrivateKey) key;
|
||||
byte[] scalar = xecKey.getScalar().orElseThrow(
|
||||
() -> new InvalidKeySpecException("No private key value")
|
||||
);
|
||||
return keySpec.cast(
|
||||
new XECPrivateKeySpec(xecKey.getParams(), scalar));
|
||||
try {
|
||||
return keySpec.cast(
|
||||
new XECPrivateKeySpec(xecKey.getParams(), scalar));
|
||||
} finally {
|
||||
Arrays.fill(scalar, (byte)0);
|
||||
}
|
||||
} else {
|
||||
throw new InvalidKeySpecException
|
||||
("KeySpec must be PKCS8EncodedKeySpec or XECPrivateKeySpec");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2021, 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
|
||||
@ -35,6 +35,7 @@ import java.security.ProviderException;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.spec.AlgorithmParameterSpec;
|
||||
import java.security.spec.NamedParameterSpec;
|
||||
import java.util.Arrays;
|
||||
|
||||
import sun.security.jca.JCAUtil;
|
||||
|
||||
@ -104,7 +105,9 @@ public class XDHKeyPairGenerator extends KeyPairGeneratorSpi {
|
||||
|
||||
byte[] privateKey = ops.generatePrivate(random);
|
||||
// computePublic may modify the private key, so clone it first
|
||||
BigInteger publicKey = ops.computePublic(privateKey.clone());
|
||||
byte[] cloned = privateKey.clone();
|
||||
BigInteger publicKey = ops.computePublic(cloned);
|
||||
Arrays.fill(cloned, (byte)0);
|
||||
|
||||
try {
|
||||
return new KeyPair(
|
||||
@ -113,6 +116,8 @@ public class XDHKeyPairGenerator extends KeyPairGeneratorSpi {
|
||||
);
|
||||
} catch (InvalidKeyException ex) {
|
||||
throw new ProviderException(ex);
|
||||
} finally {
|
||||
Arrays.fill(privateKey, (byte)0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2021, 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
|
||||
@ -49,12 +49,14 @@ public final class XDHPrivateKeyImpl extends PKCS8Key implements XECPrivateKey {
|
||||
this.k = k.clone();
|
||||
|
||||
this.algid = new AlgorithmId(params.getOid());
|
||||
DerOutputStream derKey = new DerOutputStream();
|
||||
|
||||
DerValue val = new DerValue(DerValue.tag_OctetString, k);
|
||||
try {
|
||||
derKey.putOctetString(k);
|
||||
this.key = derKey.toByteArray();
|
||||
this.key = val.toByteArray();
|
||||
} catch (IOException ex) {
|
||||
throw new AssertionError("Should not happen", ex);
|
||||
} finally {
|
||||
val.clear();
|
||||
}
|
||||
checkLength(params);
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ import java.security.InvalidKeyException;
|
||||
import java.security.ProviderException;
|
||||
import java.security.interfaces.*;
|
||||
import java.security.spec.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class EdDSAKeyFactory extends KeyFactorySpi {
|
||||
@ -79,10 +80,15 @@ public class EdDSAKeyFactory extends KeyFactorySpi {
|
||||
return result;
|
||||
} else if (key instanceof PrivateKey &&
|
||||
key.getFormat().equals("PKCS#8")) {
|
||||
EdDSAPrivateKeyImpl result =
|
||||
new EdDSAPrivateKeyImpl(key.getEncoded());
|
||||
checkLockedParams(InvalidKeyException::new, result.getParams());
|
||||
return result;
|
||||
byte[] encoded = key.getEncoded();
|
||||
try {
|
||||
EdDSAPrivateKeyImpl result =
|
||||
new EdDSAPrivateKeyImpl(encoded);
|
||||
checkLockedParams(InvalidKeyException::new, result.getParams());
|
||||
return result;
|
||||
} finally {
|
||||
Arrays.fill(encoded, (byte)0);
|
||||
}
|
||||
} else {
|
||||
throw new InvalidKeyException("Unsupported key type or format");
|
||||
}
|
||||
@ -158,17 +164,27 @@ public class EdDSAKeyFactory extends KeyFactorySpi {
|
||||
|
||||
if (keySpec instanceof PKCS8EncodedKeySpec) {
|
||||
PKCS8EncodedKeySpec pkcsSpec = (PKCS8EncodedKeySpec) keySpec;
|
||||
EdDSAPrivateKeyImpl result =
|
||||
new EdDSAPrivateKeyImpl(pkcsSpec.getEncoded());
|
||||
checkLockedParams(InvalidKeySpecException::new,
|
||||
result.getParams());
|
||||
return result;
|
||||
byte[] encoded = pkcsSpec.getEncoded();
|
||||
try {
|
||||
EdDSAPrivateKeyImpl result =
|
||||
new EdDSAPrivateKeyImpl(encoded);
|
||||
checkLockedParams(InvalidKeySpecException::new,
|
||||
result.getParams());
|
||||
return result;
|
||||
} finally {
|
||||
Arrays.fill(encoded, (byte) 0);
|
||||
}
|
||||
} else if (keySpec instanceof EdECPrivateKeySpec) {
|
||||
EdECPrivateKeySpec privateKeySpec = (EdECPrivateKeySpec) keySpec;
|
||||
EdDSAParameters params = EdDSAParameters.get(
|
||||
InvalidKeySpecException::new, privateKeySpec.getParams());
|
||||
checkLockedParams(InvalidKeySpecException::new, params);
|
||||
return new EdDSAPrivateKeyImpl(params, privateKeySpec.getBytes());
|
||||
byte[] bytes = privateKeySpec.getBytes();
|
||||
try {
|
||||
return new EdDSAPrivateKeyImpl(params, bytes);
|
||||
} finally {
|
||||
Arrays.fill(bytes, (byte)0);
|
||||
}
|
||||
} else {
|
||||
throw new InvalidKeySpecException(
|
||||
"Only PKCS8EncodedKeySpec and EdECPrivateKeySpec supported");
|
||||
@ -203,14 +219,23 @@ public class EdDSAKeyFactory extends KeyFactorySpi {
|
||||
if (!key.getFormat().equals("PKCS#8")) {
|
||||
throw new InvalidKeySpecException("Format is not PKCS#8");
|
||||
}
|
||||
return keySpec.cast(new PKCS8EncodedKeySpec(key.getEncoded()));
|
||||
byte[] encoded = key.getEncoded();
|
||||
try {
|
||||
return keySpec.cast(new PKCS8EncodedKeySpec(encoded));
|
||||
} finally {
|
||||
Arrays.fill(encoded, (byte)0);
|
||||
}
|
||||
} else if (keySpec.isAssignableFrom(EdECPrivateKeySpec.class)) {
|
||||
EdECPrivateKey edKey = (EdECPrivateKey) key;
|
||||
byte[] scalar = edKey.getBytes().orElseThrow(
|
||||
() -> new InvalidKeySpecException("No private key value")
|
||||
);
|
||||
return keySpec.cast(
|
||||
new EdECPrivateKeySpec(edKey.getParams(), scalar));
|
||||
try {
|
||||
return keySpec.cast(
|
||||
new EdECPrivateKeySpec(edKey.getParams(), scalar));
|
||||
} finally {
|
||||
Arrays.fill(scalar, (byte)0);
|
||||
}
|
||||
} else {
|
||||
throw new InvalidKeySpecException
|
||||
("KeySpec must be PKCS8EncodedKeySpec or EdECPrivateKeySpec");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2021, 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
|
||||
@ -37,6 +37,7 @@ import java.security.SecureRandom;
|
||||
import java.security.spec.AlgorithmParameterSpec;
|
||||
import java.security.spec.EdECPoint;
|
||||
import java.security.spec.NamedParameterSpec;
|
||||
import java.util.Arrays;
|
||||
|
||||
import sun.security.jca.JCAUtil;
|
||||
import sun.security.util.SecurityProviderConstants;
|
||||
@ -120,6 +121,8 @@ public class EdDSAKeyPairGenerator extends KeyPairGeneratorSpi {
|
||||
);
|
||||
} catch (InvalidKeyException ex) {
|
||||
throw new ProviderException(ex);
|
||||
} finally {
|
||||
Arrays.fill(privateKey, (byte)0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2021, 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
|
||||
@ -115,7 +115,11 @@ public class EdDSAParameters {
|
||||
}
|
||||
@Override
|
||||
public byte[] digest() {
|
||||
return md.digest();
|
||||
try {
|
||||
return md.digest();
|
||||
} finally {
|
||||
md.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -135,7 +139,11 @@ public class EdDSAParameters {
|
||||
}
|
||||
@Override
|
||||
public byte[] digest() {
|
||||
return md.digest();
|
||||
try {
|
||||
return md.digest();
|
||||
} finally {
|
||||
md.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2021, 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
|
||||
@ -51,12 +51,13 @@ public final class EdDSAPrivateKeyImpl
|
||||
this.algid = new AlgorithmId(params.getOid());
|
||||
this.h = h.clone();
|
||||
|
||||
DerOutputStream derKey = new DerOutputStream();
|
||||
DerValue val = new DerValue(DerValue.tag_OctetString, h);
|
||||
try {
|
||||
derKey.putOctetString(h);
|
||||
this.key = derKey.toByteArray();
|
||||
this.key = val.toByteArray();
|
||||
} catch (IOException ex) {
|
||||
throw new AssertionError("Should not happen", ex);
|
||||
} finally {
|
||||
val.clear();
|
||||
}
|
||||
checkLength(params);
|
||||
}
|
||||
|
@ -76,8 +76,7 @@ public class PKCS8Test {
|
||||
.formatter(ASN1Formatter.formatter())
|
||||
.toString(encodedKey));
|
||||
|
||||
PKCS8Key decodedKey = (PKCS8Key)PKCS8Key.parseKey(
|
||||
new DerValue(encodedKey));
|
||||
PKCS8Key decodedKey = (PKCS8Key)PKCS8Key.parseKey(encodedKey);
|
||||
|
||||
Assert.assertEquals(decodedKey.getAlgorithm(), ALGORITHM);
|
||||
Assert.assertEquals(decodedKey.getFormat(), FORMAT);
|
||||
@ -120,6 +119,6 @@ public class PKCS8Test {
|
||||
Assert.assertTrue(length < 127);
|
||||
original[1] = (byte)(length - 2); // the length field inside DER
|
||||
original[4] = (byte)newVersion; // the version inside DER
|
||||
PKCS8Key.parseKey(new DerValue(original));
|
||||
PKCS8Key.parseKey(original);
|
||||
}
|
||||
}
|
||||
|
@ -98,8 +98,7 @@ public class TestKeyFactory extends PKCS11Test {
|
||||
}
|
||||
@Override
|
||||
public byte[] getEncoded() {
|
||||
// skip cloning for testing key.
|
||||
return encodedPriv;
|
||||
return encodedPriv.clone();
|
||||
}
|
||||
};
|
||||
byte[] encodedPub = Base64.getDecoder().decode(PKCS1_PUB_STR);
|
||||
@ -114,8 +113,7 @@ public class TestKeyFactory extends PKCS11Test {
|
||||
}
|
||||
@Override
|
||||
public byte[] getEncoded() {
|
||||
// skip cloning for testing key.
|
||||
return encodedPub;
|
||||
return encodedPub.clone();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -97,8 +97,7 @@ public class TestKeyFactory {
|
||||
}
|
||||
@Override
|
||||
public byte[] getEncoded() {
|
||||
// skip cloning for testing key.
|
||||
return encodedPriv;
|
||||
return encodedPriv.clone();
|
||||
}
|
||||
};
|
||||
byte[] encodedPub = Base64.getDecoder().decode(PKCS1_PUB_STR);
|
||||
@ -113,8 +112,7 @@ public class TestKeyFactory {
|
||||
}
|
||||
@Override
|
||||
public byte[] getEncoded() {
|
||||
// skip cloning for testing key.
|
||||
return encodedPub;
|
||||
return encodedPub.clone();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user