提交 c55e0542 编写于 作者: W weijun

6879539: enable empty password support for pkcs12 keystore

Reviewed-by: vinnie, weijun
Contributed-by: NFlorian Weimer <fweimer@bfk.de>
上级 7df0a39e
...@@ -55,9 +55,12 @@ final class PBEKey implements SecretKey { ...@@ -55,9 +55,12 @@ final class PBEKey implements SecretKey {
// Should allow an empty password. // Should allow an empty password.
passwd = new char[0]; passwd = new char[0];
} }
for (int i=0; i<passwd.length; i++) { // Accept "\0" to signify "zero-length password with no terminator".
if ((passwd[i] < '\u0020') || (passwd[i] > '\u007E')) { if (!(passwd.length == 1 && passwd[0] == 0)) {
throw new InvalidKeySpecException("Password is not ASCII"); for (int i=0; i<passwd.length; i++) {
if ((passwd[i] < '\u0020') || (passwd[i] > '\u007E')) {
throw new InvalidKeySpecException("Password is not ASCII");
}
} }
} }
this.key = new byte[passwd.length]; this.key = new byte[passwd.length];
......
...@@ -60,11 +60,16 @@ final class PKCS12PBECipherCore { ...@@ -60,11 +60,16 @@ final class PKCS12PBECipherCore {
static byte[] derive(char[] chars, byte[] salt, static byte[] derive(char[] chars, byte[] salt,
int ic, int n, int type) { int ic, int n, int type) {
// Add in trailing NULL terminator. // Add in trailing NULL terminator. Special case:
// no terminator if password is "\0".
int length = chars.length*2; int length = chars.length*2;
if (length != 0) { if (length == 2 && chars[0] == 0) {
chars = new char[0];
length = 0;
} else {
length += 2; length += 2;
} }
byte[] passwd = new byte[length]; byte[] passwd = new byte[length];
for (int i = 0, j = 0; i < chars.length; i++, j+=2) { for (int i = 0, j = 0; i < chars.length; i++, j+=2) {
passwd[j] = (byte) ((chars[i] >>> 8) & 0xFF); passwd[j] = (byte) ((chars[i] >>> 8) & 0xFF);
...@@ -133,6 +138,9 @@ final class PKCS12PBECipherCore { ...@@ -133,6 +138,9 @@ final class PKCS12PBECipherCore {
} }
private static void concat(byte[] src, byte[] dst, int start, int len) { private static void concat(byte[] src, byte[] dst, int start, int len) {
if (src.length == 0) {
return;
}
int loop = len / src.length; int loop = len / src.length;
int off, i; int off, i;
for (i = 0, off = 0; i < loop; i++, off += src.length) for (i = 0, off = 0; i < loop; i++, off += src.length)
......
...@@ -253,11 +253,25 @@ public final class PKCS12KeyStore extends KeyStoreSpi { ...@@ -253,11 +253,25 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
} }
try { try {
// Use JCE byte[] privateKeyInfo;
SecretKey skey = getPBEKey(password); while (true) {
Cipher cipher = Cipher.getInstance(algOid.toString()); try {
cipher.init(Cipher.DECRYPT_MODE, skey, algParams); // Use JCE
byte[] privateKeyInfo = cipher.doFinal(encryptedKey); SecretKey skey = getPBEKey(password);
Cipher cipher = Cipher.getInstance(algOid.toString());
cipher.init(Cipher.DECRYPT_MODE, skey, algParams);
privateKeyInfo = cipher.doFinal(encryptedKey);
break;
} catch (Exception e) {
if (password.length == 0) {
// Retry using an empty password
// without a NULL terminator.
password = new char[1];
continue;
}
throw e;
}
}
PKCS8EncodedKeySpec kspec = new PKCS8EncodedKeySpec(privateKeyInfo); PKCS8EncodedKeySpec kspec = new PKCS8EncodedKeySpec(privateKeyInfo);
...@@ -1251,16 +1265,24 @@ public final class PKCS12KeyStore extends KeyStoreSpi { ...@@ -1251,16 +1265,24 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
ObjectIdentifier algOid = in.getOID(); ObjectIdentifier algOid = in.getOID();
AlgorithmParameters algParams = parseAlgParameters(in); AlgorithmParameters algParams = parseAlgParameters(in);
try { while (true) {
// Use JCE try {
SecretKey skey = getPBEKey(password); // Use JCE
Cipher cipher = Cipher.getInstance(algOid.toString()); SecretKey skey = getPBEKey(password);
cipher.init(Cipher.DECRYPT_MODE, skey, algParams); Cipher cipher = Cipher.getInstance(algOid.toString());
safeContentsData = cipher.doFinal(safeContentsData); cipher.init(Cipher.DECRYPT_MODE, skey, algParams);
safeContentsData = cipher.doFinal(safeContentsData);
} catch (Exception e) { break;
throw new IOException("failed to decrypt safe" } catch (Exception e) {
+ " contents entry: " + e, e); if (password.length == 0) {
// Retry using an empty password
// without a NULL terminator.
password = new char[1];
continue;
}
throw new IOException(
"failed to decrypt safe contents entry: " + e, e);
}
} }
} else { } else {
throw new IOException("public key protected PKCS12" + throw new IOException("public key protected PKCS12" +
......
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册