SpongyCastle: Error while finalizing cipher

2019-07-27 00:25发布

问题:

in an Android project I need to authenticate my app for an https connection. Using the following method I'm trying to decrypt my private key, provided by the server developers in a .pem file. I use SpongyCastle, and at the top of the same class where the methods are I already changed the security provider like this:

    static {
    Security.insertProviderAt(new org.spongycastle.jce.provider.BouncyCastleProvider(), 1);
}

In this case my object is an instance of PKCS8EncryptedPrivateKeyInfo. This is the method:

    /**
     * Parses a PrivateKey instance from a PEM representation.
     *
     * When the provided key is encrypted, the provided pass phrase is applied.
     *
     * @param pemRepresentation a PEM representation of a private key (cannot be null or empty)
     * @param passPhrase optional pass phrase (must be present if the private key is encrypted).
     * @return a PrivateKey instance (never null)
     */
public static PrivateKey parsePrivateKey(InputStream pemRepresentation, String passPhrase) throws IOException {

if ( passPhrase == null ) {
    passPhrase = "";
}
try (Reader reader = new InputStreamReader(pemRepresentation); //
        PEMParser pemParser = new PEMParser(reader)) {

    final Object object = pemParser.readObject();
    final JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider( "BC" );

    final KeyPair kp;

    if ( object instanceof PEMEncryptedKeyPair )
    {
        // Encrypted key - we will use provided password
        final PEMDecryptorProvider decProv = new JcePEMDecryptorProviderBuilder().build( passPhrase.toCharArray() );
        kp = converter.getKeyPair( ( (PEMEncryptedKeyPair) object ).decryptKeyPair( decProv ) );
    }
    else if ( object instanceof PKCS8EncryptedPrivateKeyInfo )
    {
        // Encrypted key - we will use provided password
        try
        {
            final PKCS8EncryptedPrivateKeyInfo encryptedInfo = (PKCS8EncryptedPrivateKeyInfo) object;
            final InputDecryptorProvider provider = new JceOpenSSLPKCS8DecryptorProviderBuilder().build( passPhrase.toCharArray() );
            final PrivateKeyInfo privateKeyInfo = encryptedInfo.decryptPrivateKeyInfo( provider );
            return converter.getPrivateKey( privateKeyInfo );
        }
        catch ( PKCSException | OperatorCreationException e )
        {
            throw new IOException( "Unable to decrypt private key.", e );
        }
    }
    else if ( object instanceof PrivateKeyInfo )
    {
        return converter.getPrivateKey( (PrivateKeyInfo) object );
    }
    else
    {
        // Unencrypted key - no password needed
        kp = converter.getKeyPair( (PEMKeyPair) object );
    }
    return kp.getPrivate();
}
}

When I arrive at:

encryptedInfo.decryptPrivateKeyInfo( provider );

I encounter the following exception:

org.spongycastle.pkcs.PKCSException: unable to read encrypted data: Error while finalizing cipher
    at org.spongycastle.pkcs.PKCS8EncryptedPrivateKeyInfo.decryptPrivateKeyInfo(PKCS8EncryptedPrivateKeyInfo.java:73)
    [...]
    at android.view.View.performClick(View.java:5184)
    at android.view.View$PerformClick.run(View.java:20893)
    at android.os.Handler.handleCallback(Handler.java:739)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:145)
    at android.app.ActivityThread.main(ActivityThread.java:5938)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1400)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1195)
Caused by: java.io.IOException: Error while finalizing cipher
    at javax.crypto.CipherInputStream.fillBuffer(CipherInputStream.java:104)
    at javax.crypto.CipherInputStream.read(CipherInputStream.java:155)
    at org.spongycastle.util.io.Streams.pipeAll(Streams.java:114)
    at org.spongycastle.util.io.Streams.readAll(Streams.java:41)
    at org.spongycastle.pkcs.PKCS8EncryptedPrivateKeyInfo.decryptPrivateKeyInfo(PKCS8EncryptedPrivateKeyInfo.java:69)
    ... 21 more
Caused by: javax.crypto.BadPaddingException: pad block corrupted
    at org.spongycastle.jcajce.provider.symmetric.util.BaseBlockCipher$BufferedGenericBlockCipher.doFinal(BaseBlockCipher.java:1227)
    at org.spongycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineDoFinal(BaseBlockCipher.java:1103)
    at javax.crypto.Cipher.doFinal(Cipher.java:1314)
    at javax.crypto.CipherInputStream.fillBuffer(CipherInputStream.java:102)
    ... 25 more

Any suggestion? Thanks.