-
Bug
-
Resolution: Duplicate
-
P4
-
None
-
6u10
-
x86
-
windows_xp
FULL PRODUCT VERSION :
java version "1.6.0_20"
Java(TM) SE Runtime Environment (build 1.6.0_20-b02)
Java HotSpot(TM) Client VM (build 16.3-b01, mixed mode, sharing)
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]
A DESCRIPTION OF THE PROBLEM :
When a PKCS12 keystore (SunJSSE provider) is loaded with invalid password, some wrong passwords generate a "Sequence tag error" and not the "failed to decrypt safe contents entry: javax.crypto.BadPaddingException: Given final block not properly padded" as message text in the IOException.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Load the PKCS12 keystore with a sequence of invalid passwords and and sometimes you see the incorrect message in the IOException.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Always the same IOExcetion.
java.io.IOException: failed to decrypt safe contents entry: javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.net.ssl.internal.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeyStore.java:1277)
at java.security.KeyStore.load(KeyStore.java:1185)
at Test.run(Test.java:80)
at Test.main(Test.java:182)
Caused by: javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
at com.sun.crypto.provider.PKCS12PBECipherCore.b(DashoA13*..)
at com.sun.crypto.provider.PKCS12PBECipherCore$PBEWithSHA1AndRC2_40.engineDoFinal(DashoA13*..)
at javax.crypto.Cipher.doFinal(DashoA13*..)
at com.sun.net.ssl.internal.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeyStore.java:1274)
... 3 more
ACTUAL -
Sometimes:
java.io.IOException: Sequence tag error
at sun.security.util.DerInputStream.getSequence(DerInputStream.java:280)
at com.sun.net.ssl.internal.pkcs12.PKCS12KeyStore.loadSafeContents(PKCS12KeyStore.java:1355)
at com.sun.net.ssl.internal.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeyStore.java:1287)
at java.security.KeyStore.load(KeyStore.java:1185)
at Test.run(Test.java:99)
at Test.main(Test.java:182)
ERROR MESSAGES/STACK TRACES THAT OCCUR :
see above
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import sun.misc.BASE64Decoder;
public class Test {
String p12KeyStore = "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\n"
+ "xu5CkKPQGKVyhXQkDAUIAgIEAA==";
private KeyStore store = null;
private Test() throws Exception {
store = KeyStore.getInstance("PKCS12", "SunJSSE");
store.load(null, null);
}
private void run() throws Exception {
InputStream is;
String pwd = null;
byte [] p12 = new BASE64Decoder().decodeBuffer(p12KeyStore);
ByteArrayInputStream storeStream = new ByteArrayInputStream(p12);
is = storeStream;
is.mark(0);
//incorrect PIN
pwd = "100000";
try {
store.load(is, pwd.toCharArray());
System.out.println("PIN '" + pwd + "' OK");
}
catch (IOException e) {
e.printStackTrace();
System.out.println("Error message for PIN '" + pwd + "': " + e.getMessage());
}
finally {
is.reset();
}
System.out.println();
//incorrect PIN
pwd = "100872";
try {
store.load(is, pwd.toCharArray());
System.out.println("PIN '" + pwd + "' OK");
}
catch (IOException e) {
e.printStackTrace();
System.out.println("Error message for PIN '" + pwd + "': " + e.getMessage());
}
finally {
is.reset();
}
System.out.println();
//correct PIN
pwd = "123456";
try {
store.load(is, pwd.toCharArray());
System.out.println("PIN '" + pwd + "' OK");
}
catch (IOException e) {
System.out.println("Error message for PIN '" + pwd + "': " + e.getMessage());
}
finally {
is.close();
}
}
public static void main(String [] args) {
try {
(new Test()).run();
}
catch (Throwable e) {
e.printStackTrace();
System.exit(1);
}
System.exit(0);
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Doing the MAC verification manually before loading the PKCS12 keystore.
----------------------------------------------------------------------------------------------------
Possible solution in sun.security.pkcs12.PKCS12KeyStore
public synchronized void engineLoad(InputStream stream,
char[] password) throws IOException,
NoSuchAlgorithmException, CertificateException {
DataInputStream dis;
CertificateFactory cf = null;
ByteArrayInputStream bais = null;
byte[] encoded = null;
if (stream == null)
return;
// reset the counter
counter = 0;
DerValue val = new DerValue(stream);
DerInputStream derInStream = val.toDerInputStream();
//Parse Input
int version = derInStream.getInteger();
ContentInfo authSafe = new ContentInfo(derInStream);
MacData macData = null;
// The MacData is optional.
if (derInStream.available() > 0){
macData = new MacData(derInStream);
}
//Check version
if (version != VERSION_3) {
throw new IOException(
"PKCS12 keystore not in version 3 format");
}
entries.clear();
/*
* Read the authSafe.
*/
byte[] authSafeData;
ObjectIdentifier contentType = authSafe.getContentType();
if (contentType.equals(ContentInfo.DATA_OID)) {
authSafeData = authSafe.getData();
} else /* signed data */{
throw new IOException(
"public key protected PKCS12 not supported");
}
//Now have all data for Mac check
if (password != null && macData != null) {
try {
String algName = macData.getDigestAlgName()
.toUpperCase();
if (algName.equals("SHA") || algName.equals("SHA1")
|| algName.equals("SHA-1")) {
algName = "SHA1";
}
// generate MAC (MAC key is created within JCE)
Mac m = Mac.getInstance("HmacPBE" + algName);
PBEParameterSpec params = new PBEParameterSpec(macData.getSalt(), macData.getIterations());
SecretKey key = getPBEKey(password);
m.init(key, params);
m.update(authSafeData);
byte[] macResult = m.doFinal();
if (!Arrays.equals(macData.getDigest(), macResult)) {
//throw new SecurityException("Failed PKCS12 integrity checking");
throw new SecurityException("Mac verify error: invalid password?");
}
} catch (Exception e) {
IOException ioe = new IOException(
"Integrity check failed: " + e);
ioe.initCause(e);
throw ioe;
}
}
// ... Additional code
}
java version "1.6.0_20"
Java(TM) SE Runtime Environment (build 1.6.0_20-b02)
Java HotSpot(TM) Client VM (build 16.3-b01, mixed mode, sharing)
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]
A DESCRIPTION OF THE PROBLEM :
When a PKCS12 keystore (SunJSSE provider) is loaded with invalid password, some wrong passwords generate a "Sequence tag error" and not the "failed to decrypt safe contents entry: javax.crypto.BadPaddingException: Given final block not properly padded" as message text in the IOException.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Load the PKCS12 keystore with a sequence of invalid passwords and and sometimes you see the incorrect message in the IOException.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Always the same IOExcetion.
java.io.IOException: failed to decrypt safe contents entry: javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.net.ssl.internal.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeyStore.java:1277)
at java.security.KeyStore.load(KeyStore.java:1185)
at Test.run(Test.java:80)
at Test.main(Test.java:182)
Caused by: javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
at com.sun.crypto.provider.PKCS12PBECipherCore.b(DashoA13*..)
at com.sun.crypto.provider.PKCS12PBECipherCore$PBEWithSHA1AndRC2_40.engineDoFinal(DashoA13*..)
at javax.crypto.Cipher.doFinal(DashoA13*..)
at com.sun.net.ssl.internal.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeyStore.java:1274)
... 3 more
ACTUAL -
Sometimes:
java.io.IOException: Sequence tag error
at sun.security.util.DerInputStream.getSequence(DerInputStream.java:280)
at com.sun.net.ssl.internal.pkcs12.PKCS12KeyStore.loadSafeContents(PKCS12KeyStore.java:1355)
at com.sun.net.ssl.internal.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeyStore.java:1287)
at java.security.KeyStore.load(KeyStore.java:1185)
at Test.run(Test.java:99)
at Test.main(Test.java:182)
ERROR MESSAGES/STACK TRACES THAT OCCUR :
see above
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import sun.misc.BASE64Decoder;
public class Test {
String p12KeyStore = "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\n"
+ "xu5CkKPQGKVyhXQkDAUIAgIEAA==";
private KeyStore store = null;
private Test() throws Exception {
store = KeyStore.getInstance("PKCS12", "SunJSSE");
store.load(null, null);
}
private void run() throws Exception {
InputStream is;
String pwd = null;
byte [] p12 = new BASE64Decoder().decodeBuffer(p12KeyStore);
ByteArrayInputStream storeStream = new ByteArrayInputStream(p12);
is = storeStream;
is.mark(0);
//incorrect PIN
pwd = "100000";
try {
store.load(is, pwd.toCharArray());
System.out.println("PIN '" + pwd + "' OK");
}
catch (IOException e) {
e.printStackTrace();
System.out.println("Error message for PIN '" + pwd + "': " + e.getMessage());
}
finally {
is.reset();
}
System.out.println();
//incorrect PIN
pwd = "100872";
try {
store.load(is, pwd.toCharArray());
System.out.println("PIN '" + pwd + "' OK");
}
catch (IOException e) {
e.printStackTrace();
System.out.println("Error message for PIN '" + pwd + "': " + e.getMessage());
}
finally {
is.reset();
}
System.out.println();
//correct PIN
pwd = "123456";
try {
store.load(is, pwd.toCharArray());
System.out.println("PIN '" + pwd + "' OK");
}
catch (IOException e) {
System.out.println("Error message for PIN '" + pwd + "': " + e.getMessage());
}
finally {
is.close();
}
}
public static void main(String [] args) {
try {
(new Test()).run();
}
catch (Throwable e) {
e.printStackTrace();
System.exit(1);
}
System.exit(0);
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Doing the MAC verification manually before loading the PKCS12 keystore.
----------------------------------------------------------------------------------------------------
Possible solution in sun.security.pkcs12.PKCS12KeyStore
public synchronized void engineLoad(InputStream stream,
char[] password) throws IOException,
NoSuchAlgorithmException, CertificateException {
DataInputStream dis;
CertificateFactory cf = null;
ByteArrayInputStream bais = null;
byte[] encoded = null;
if (stream == null)
return;
// reset the counter
counter = 0;
DerValue val = new DerValue(stream);
DerInputStream derInStream = val.toDerInputStream();
//Parse Input
int version = derInStream.getInteger();
ContentInfo authSafe = new ContentInfo(derInStream);
MacData macData = null;
// The MacData is optional.
if (derInStream.available() > 0){
macData = new MacData(derInStream);
}
//Check version
if (version != VERSION_3) {
throw new IOException(
"PKCS12 keystore not in version 3 format");
}
entries.clear();
/*
* Read the authSafe.
*/
byte[] authSafeData;
ObjectIdentifier contentType = authSafe.getContentType();
if (contentType.equals(ContentInfo.DATA_OID)) {
authSafeData = authSafe.getData();
} else /* signed data */{
throw new IOException(
"public key protected PKCS12 not supported");
}
//Now have all data for Mac check
if (password != null && macData != null) {
try {
String algName = macData.getDigestAlgName()
.toUpperCase();
if (algName.equals("SHA") || algName.equals("SHA1")
|| algName.equals("SHA-1")) {
algName = "SHA1";
}
// generate MAC (MAC key is created within JCE)
Mac m = Mac.getInstance("HmacPBE" + algName);
PBEParameterSpec params = new PBEParameterSpec(macData.getSalt(), macData.getIterations());
SecretKey key = getPBEKey(password);
m.init(key, params);
m.update(authSafeData);
byte[] macResult = m.doFinal();
if (!Arrays.equals(macData.getDigest(), macResult)) {
//throw new SecurityException("Failed PKCS12 integrity checking");
throw new SecurityException("Mac verify error: invalid password?");
}
} catch (Exception e) {
IOException ioe = new IOException(
"Integrity check failed: " + e);
ioe.initCause(e);
throw ioe;
}
}
// ... Additional code
}