I have a PEM-encoded private key and I need to sign a string with it. But the code keeps crashing with exception:
java.security.spec.InvalidKeySpecException: java.lang.RuntimeException: error:0c0890ba:ASN.1 encoding routines:asn1_check_tlen:WRONG_TAG
the key string:
-----BEGIN ENCRYPTED PRIVATE KEY----- MIICxjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQI4P/+9mJV6RwCAggA MBQGCCqGSIb3DQMHBAg/ZWGXeLHgeASCAoAhExhFxfcikmIKbFP0rgAlJuj1r999 ... and so on... hlgzM2p71FdC6NDVyyxbit/IzbimtJyhkRwOAnZ98yqtXWUEOx2v7CcUqiU8dSLA K0PsaxNTUeUcQV+Z7yJk/8HxfE1ya3u2CgPXCZsWWmbxQG/+awE0eEnZ -----END ENCRYPTED PRIVATE KEY-----
I've tried many variants, looked through many answers, but the results were the same
Edit: with James K Polk's help I've managed to get private key bytes, but now I get java.security.NoSuchAlgorithmException: SecretKeyFactory PBES2 implementation not found.
Modified code:
private String sign(String dataString, String pkString, String privateKeyPass) throws Exception { pkString = pkString.replace("-----BEGIN ENCRYPTED PRIVATE KEY-----", ""); pkString = pkString.replace("-----END ENCRYPTED PRIVATE KEY-----", ""); pkString = pkString.replaceAll("\\s+",""); byte[] privateKeyBytes = decryptPrivateKey(Base64.decode(pkString, Base64.DEFAULT), privateKeyPass); KeyFactory kf = KeyFactory.getInstance("RSA"); PrivateKey privateKey = kf.generatePrivate(new PKCS8EncodedKeySpec(privateKeyBytes)); Signature instance = Signature.getInstance("SHA1withRSA"); instance.initSign(privateKey); instance.update(dataString.getBytes(UTF_8)); return Base64.encodeToString(instance.sign(), Base64.DEFAULT); } public static byte[] decryptPrivateKey(byte[] key, String pass) throws Exception { PBEKeySpec passKeySpec = new PBEKeySpec(pass.toCharArray()); EncryptedPrivateKeyInfo encryptedKey = new EncryptedPrivateKeyInfo(key); Timber.w("encryptedKey.getAlgName(): %s", encryptedKey.getAlgName()); SecretKeyFactory keyFac = SecretKeyFactory.getInstance(encryptedKey.getAlgName());//PBES2 SecretKey passKey = keyFac.generateSecret(passKeySpec); // Create PBE Cipher Cipher pbeCipher = Cipher.getInstance(encryptedKey.getAlgName()); // Initialize PBE Cipher with key and parameters pbeCipher.init(Cipher.DECRYPT_MODE, passKey, encryptedKey.getAlgParameters()); // Decrypt the private key return pbeCipher.doFinal(encryptedKey.getEncryptedData()); }
EDIT: I ended up using class from http://commandlinefanatic.com/cgi-bin/showarticle.cgi?article=art050:
PrivateKey privateKey = KeyImport.readPrivateKeyFile(pkFileName, privateKeyPass);
I save keyString into a file and then feed it to readPrivateKeyFile