여기에 Basscy Castle PGP 암호화 + 부호가 하나의 패스로 구현되었습니다. 서명이 검증 된 것으로 보이지만 페이로드가 해독되지 않습니다.
public class SinglePassSignedEncryptedFileProcessor {
private static final Logger logger = LoggerFactory.getLogger(SinglePassSignedEncryptedFileProcessor.class);
/*
* This is the primary function that will create encrypt a file and sign it
* with a one pass signature. This leans on an C# example by John Opincar
* @author Bilal Soylu
* @param targetFileName
* -- file name on drive systems that will contain encrypted content
* @param embeddedFileName
* -- the original file name before encryption
* @param secretKeyRingInputStream
* -- Private Key Ring File
* @param targetFileStream
* -- The stream for the encrypted target file
* @param secretKeyPassphrase
* -- The private key password for the key retrieved from
* collection used for signing
* @param signPublicKeyInputStream
* -- the public key of the target recipient to be used to
* encrypt the file
* @throws Exception
*/
public void encryptOnePassSign(
String fileName,
InputStream keyIn,
OutputStream out,
char[] pass,
PGPPublicKey encryptionKey,
boolean armor,
boolean withIntegrityCheck,
String providerName)
throws IOException, NoSuchAlgorithmException, NoSuchProviderException, PGPException, SignatureException {
if (armor) {
out = new ArmoredOutputStream(out);
}
// Compress
byte[] bytes = PGPEncryptUtil.compressFile(fileName, CompressionAlgorithmTags.ZIP);
// Encryption process.
PGPEncryptedDataGenerator encGen = new PGPEncryptedDataGenerator(
new JcePGPDataEncryptorBuilder(PGPEncryptedData.CAST5).setWithIntegrityPacket(withIntegrityCheck).setSecureRandom(new SecureRandom()).setProvider("BC"));
encGen.addMethod(new JcePublicKeyKeyEncryptionMethodGenerator(encryptionKey).setProvider("BC"));
ByteArrayOutputStream encryptedOutputStream = new ByteArrayOutputStream();
OutputStream encryptedOut = encGen.open(encryptedOutputStream, bytes);
encryptedOut.write(bytes);
encryptedOut.close();
byte[] bytesEncrypted = encryptedOutputStream.toByteArray();
encryptedOutputStream.close();
// Signing process.
PGPSecretKey pgpSec = PGPEncryptUtil.readSecretKey(keyIn);
PGPPrivateKey pgpPrivKey = pgpSec.extractPrivateKey(new JcePBESecretKeyDecryptorBuilder().setProvider("BC").build(pass));
PGPSignatureGenerator sGen = new PGPSignatureGenerator(new JcaPGPContentSignerBuilder(pgpSec.getPublicKey().getAlgorithm(), PGPUtil.SHA1).setProvider("BC"));
sGen.init(PGPSignature.BINARY_DOCUMENT, pgpPrivKey);
Iterator it = pgpSec.getPublicKey().getUserIDs();
if (it.hasNext()) {
PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();
spGen.setSignerUserID(false, (String) it.next());
sGen.setHashedSubpackets(spGen.generate());
}
PGPCompressedDataGenerator cGen = new PGPCompressedDataGenerator(
PGPCompressedData.UNCOMPRESSED);
// Write to the output stream.
BCPGOutputStream bOut = new BCPGOutputStream(cGen.open(out));
sGen.generateOnePassVersion(false).encode(bOut);
File file = new File(fileName);
PGPLiteralDataGenerator lGen = new PGPLiteralDataGenerator();
// file is encoding name.
Date lastModified = new Date(file.lastModified());
OutputStream lOut = lGen.open(bOut, PGPLiteralData.BINARY, fileName, lastModified, bytesEncrypted);
//FileInputStream fIn = new FileInputStream(file);
//int ch;
//while ((ch = fIn.read()) >= 0) {
lOut.write(bytesEncrypted);
sGen.update(bytesEncrypted);
// }
// ?
lGen.close();
sGen.generate().encode(bOut);
cGen.close();
if (armor) {
out.close();
}
// close everything down we are done
/*
literalOut.close();
literalDataGenerator.close();
signatureGenerator.generate().encode(compressedOut);
compressedOut.close();
compressedDataGenerator.close();
encryptedOut.close();
encryptedDataGenerator.close();
*/
// if (armor) targetFileStream.close();
}
}
다음과 같은 세 가지 방법으로 인증합니다. 암호화, 인증 및 암호화 (원하는 것으로 보이는 것) 및 암호화 후 인증. 보안은 세 가지 모두에 대해 동일하지 않습니다. Moxie의 입장은 해독시 인증 전에 가능한 한 작게 수행해야한다는 것입니다. 사실 TLS AES/CBC의 한 가지 취약점은 Mac을 암호화하지 않는다는 것입니다. 선택은 보안에 영향을 미칩니다. [The Cryptographic Doom Principle] (https://moxie.org/blog/the-cryptographic-doom-principle/) – zaph