Reputation: 31
I have a JCEKS keystore to hold my AES keys. This has been working in the dev environment and in the GAE runtime for a while.
Last night I deployed an update (nothing to do with the crypto cases) and now loading the keystore throws an IOException: com.sun.crypto.provider.SealedObjectForKeyProtector and subsequently none of my crypto works (as you'd expect given I can't get to the keys).
I've Googled the exception - one lead looked promising: Convert a key of JCEKS of a provider into another store for another provider ... which suggests that a keytore created with one provider cannot be read with another provider, but that doesn't seem to be the case here as it was working yesterday! Also https://access.redhat.com/documentation/en-US/JBoss_Enterprise_Application_Platform/6.2/html/Administration_and_Configuration_Guide/sect-Password_Vaults_for_Sensitive_Strings.html suggests incompatible providers.
I rolled back my app to the previous (working) version, but I get the same error.
Has GAE changed its default provider? Should I explicitly declare the required provider in my code?
Thanks Steve
Update 20/05/2015 - root cause identified
The problem was the IOException thrown by ks.load() below:
final KeyStore ks = KeyStore.getInstance(KEYSTORE_TYPE_JCEKS);
try {
InputStream is = this.getClass().getClassLoader().getResourceAsStream("squirrol.keystore");
ks.load(is, getKeystorePassword().toCharArray()); // IOException thrown here
...
} catch (NoSuchAlgorithmException | CertificateException | IOException e) {
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
throw new KeyStoreException("Failed to load KeyStore: " + e.getLocalizedMessage());
}
The stack trace output leads off with:
at com.sun.crypto.provider.JceKeyStore.engineLoad(JceKeyStore.java:844)
Googling the class name has found the source (possibly not the actual source, but the line number in the stack trace aligns). Line 844 suggests this IOException is thrown as the result of a ClassNotFoundException with the message being the name of the class that wasn't found - in this case com.sun.crypto.provider.SealedObjectForKeyProtector:
http://www.docjar.com/html/api/com/sun/crypto/provider/JceKeyStore.java.html
So, root cause is that the Google App Engine runtime v1.9.21 cannot load the keystore because it cannot load the class com.sun.crypto.provider.SealedObjectForKeyProtector which Google admit is a whitelisting issue.
Temporary resolution As the result of a support ticket, Google have reverted my runtime back to 1.9.20 which doesn't have this problem. I'm awaiting a fix that allows me to get back onto automated engine updates.
Update 04/06/15 - Resolved Google will have a fix in the v1.9.22 runtime.
Update 11/06/15 - Not Resolved after all The problem persists in the v1.9.22 runtime :(
Update 30/06/15 - Really resolved & proven Google fixed it in the v1.9.23 runtime. Answer updated to reflect.
Upvotes: 3
Views: 4901
Reputation: 31
This is confirmed fixed in the GAE runtime 1.9.23 (not 1.9.22 - it missed the cut).
The problem was with the runtime whitelisting, which omitted one or more classes needed to load the JCEKS keystore.
This problem only affects the GAE runtimes 1.9.21 & 1.9.22. Note this is the server engine version, not the SDK version. You can check the server version in the console.
Upvotes: 1