private byte[] fetchSymmetricKeyData(PGPPrivateKey privKey, Provider asymProvider) throws PGPException { Cipher c1 = getKeyCipher(keyData.getAlgorithm(), asymProvider); try { c1.init(Cipher.DECRYPT_MODE, privKey.getKey()); } catch (InvalidKeyException e) { throw new PGPException("error setting asymmetric cipher", e); } BigInteger[] keyD = keyData.getEncSessionKey(); if (keyData.getAlgorithm() == PGPPublicKey.RSA_ENCRYPT || keyData.getAlgorithm() == PGPPublicKey.RSA_GENERAL) { byte[] bi = keyD[0].toByteArray(); if (bi[0] == 0) { c1.update(bi, 1, bi.length - 1); } else { c1.update(bi); } } else { ElGamalKey k = (ElGamalKey) privKey.getKey(); int size = (k.getParameters().getP().bitLength() + 7) / 8; byte[] tmp = new byte[size]; byte[] bi = keyD[0].toByteArray(); if (bi.length > size) { c1.update(bi, 1, bi.length - 1); } else { System.arraycopy(bi, 0, tmp, tmp.length - bi.length, bi.length); c1.update(tmp); } bi = keyD[1].toByteArray(); for (int i = 0; i != tmp.length; i++) { tmp[i] = 0; } if (bi.length > size) { c1.update(bi, 1, bi.length - 1); } else { System.arraycopy(bi, 0, tmp, tmp.length - bi.length, bi.length); c1.update(tmp); } } byte[] plain; try { plain = c1.doFinal(); } catch (Exception e) { throw new PGPException("exception decrypting secret key", e); } if (!confirmCheckSum(plain)) { throw new PGPKeyValidationException("key checksum failed"); } return plain; }
private static SecretKeyPacket buildSecretKeyPacket( boolean isMasterKey, PGPPrivateKey privKey, PGPPublicKey pubKey, PBESecretKeyEncryptor keyEncryptor, PGPDigestCalculator checksumCalculator) throws PGPException { BCPGObject secKey = (BCPGObject) privKey.getPrivateKeyDataPacket(); if (secKey == null) { if (isMasterKey) { return new SecretKeyPacket( pubKey.publicPk, SymmetricKeyAlgorithmTags.NULL, null, null, new byte[0]); } else { return new SecretSubkeyPacket( pubKey.publicPk, SymmetricKeyAlgorithmTags.NULL, null, null, new byte[0]); } } try { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); BCPGOutputStream pOut = new BCPGOutputStream(bOut); pOut.writeObject(secKey); byte[] keyData = bOut.toByteArray(); pOut.write(checksum(checksumCalculator, keyData, keyData.length)); int encAlgorithm = (keyEncryptor != null) ? keyEncryptor.getAlgorithm() : SymmetricKeyAlgorithmTags.NULL; if (encAlgorithm != SymmetricKeyAlgorithmTags.NULL) { keyData = bOut.toByteArray(); // include checksum byte[] encData = keyEncryptor.encryptKeyData(keyData, 0, keyData.length); byte[] iv = keyEncryptor.getCipherIV(); S2K s2k = keyEncryptor.getS2K(); int s2kUsage; if (checksumCalculator != null) { if (checksumCalculator.getAlgorithm() != HashAlgorithmTags.SHA1) { throw new PGPException("only SHA1 supported for key checksum calculations."); } s2kUsage = SecretKeyPacket.USAGE_SHA1; } else { s2kUsage = SecretKeyPacket.USAGE_CHECKSUM; } if (isMasterKey) { return new SecretKeyPacket(pubKey.publicPk, encAlgorithm, s2kUsage, s2k, iv, encData); } else { return new SecretSubkeyPacket(pubKey.publicPk, encAlgorithm, s2kUsage, s2k, iv, encData); } } else { if (isMasterKey) { return new SecretKeyPacket(pubKey.publicPk, encAlgorithm, null, null, bOut.toByteArray()); } else { return new SecretSubkeyPacket( pubKey.publicPk, encAlgorithm, null, null, bOut.toByteArray()); } } } catch (PGPException e) { throw e; } catch (Exception e) { throw new PGPException("Exception encrypting key", e); } }