mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-11-06 04:26:00 +01:00
Small clean-ups in OpenPgpMessageInputStream
This commit is contained in:
parent
3e120fbf7f
commit
dfb7d068bd
1 changed files with 43 additions and 65 deletions
|
@ -109,7 +109,7 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
* @throws PGPException in case of an OpenPGP error
|
* @throws PGPException in case of an OpenPGP error
|
||||||
*/
|
*/
|
||||||
public static OpenPgpMessageInputStream create(@Nonnull InputStream inputStream,
|
public static OpenPgpMessageInputStream create(@Nonnull InputStream inputStream,
|
||||||
@Nonnull ConsumerOptions options)
|
@Nonnull ConsumerOptions options)
|
||||||
throws IOException, PGPException {
|
throws IOException, PGPException {
|
||||||
return create(inputStream, options, PGPainless.getPolicy());
|
return create(inputStream, options, PGPainless.getPolicy());
|
||||||
}
|
}
|
||||||
|
@ -127,8 +127,8 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
* @throws IOException in case of an IO error
|
* @throws IOException in case of an IO error
|
||||||
*/
|
*/
|
||||||
public static OpenPgpMessageInputStream create(@Nonnull InputStream inputStream,
|
public static OpenPgpMessageInputStream create(@Nonnull InputStream inputStream,
|
||||||
@Nonnull ConsumerOptions options,
|
@Nonnull ConsumerOptions options,
|
||||||
@Nonnull Policy policy)
|
@Nonnull Policy policy)
|
||||||
throws PGPException, IOException {
|
throws PGPException, IOException {
|
||||||
return create(inputStream, options, new MessageMetadata.Message(), policy);
|
return create(inputStream, options, new MessageMetadata.Message(), policy);
|
||||||
}
|
}
|
||||||
|
@ -479,9 +479,9 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
for (Passphrase passphrase : options.getDecryptionPassphrases()) {
|
for (Passphrase passphrase : options.getDecryptionPassphrases()) {
|
||||||
for (PGPPBEEncryptedData skesk : esks.skesks) {
|
for (PGPPBEEncryptedData skesk : esks.skesks) {
|
||||||
LOGGER.debug("Attempt decryption with provided passphrase");
|
LOGGER.debug("Attempt decryption with provided passphrase");
|
||||||
SymmetricKeyAlgorithm kekAlgorithm = SymmetricKeyAlgorithm.requireFromId(skesk.getAlgorithm());
|
SymmetricKeyAlgorithm encapsulationAlgorithm = SymmetricKeyAlgorithm.requireFromId(skesk.getAlgorithm());
|
||||||
try {
|
try {
|
||||||
throwIfUnacceptable(kekAlgorithm);
|
throwIfUnacceptable(encapsulationAlgorithm);
|
||||||
} catch (UnacceptableAlgorithmException e) {
|
} catch (UnacceptableAlgorithmException e) {
|
||||||
LOGGER.debug("Skipping SKESK with unacceptable encapsulation algorithm", e);
|
LOGGER.debug("Skipping SKESK with unacceptable encapsulation algorithm", e);
|
||||||
continue;
|
continue;
|
||||||
|
@ -489,7 +489,6 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
|
|
||||||
PBEDataDecryptorFactory decryptorFactory = ImplementationFactory.getInstance()
|
PBEDataDecryptorFactory decryptorFactory = ImplementationFactory.getInstance()
|
||||||
.getPBEDataDecryptorFactory(passphrase);
|
.getPBEDataDecryptorFactory(passphrase);
|
||||||
|
|
||||||
if (decryptSKESKAndStream(skesk, decryptorFactory)) {
|
if (decryptSKESKAndStream(skesk, decryptorFactory)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -497,10 +496,11 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Tuple<PGPSecretKey, PGPPublicKeyEncryptedData>> postponedDueToMissingPassphrase = new ArrayList<>();
|
List<Tuple<PGPSecretKey, PGPPublicKeyEncryptedData>> postponedDueToMissingPassphrase = new ArrayList<>();
|
||||||
|
|
||||||
// Try (known) secret keys
|
// Try (known) secret keys
|
||||||
for (PGPPublicKeyEncryptedData pkesk : esks.pkesks) {
|
for (PGPPublicKeyEncryptedData pkesk : esks.pkesks) {
|
||||||
long keyId = pkesk.getKeyID();
|
long keyId = pkesk.getKeyID();
|
||||||
LOGGER.debug("Encountered PKESK with recipient " + KeyIdUtil.formatKeyId(keyId));
|
LOGGER.debug("Encountered PKESK for recipient " + KeyIdUtil.formatKeyId(keyId));
|
||||||
PGPSecretKeyRing decryptionKeys = getDecryptionKey(keyId);
|
PGPSecretKeyRing decryptionKeys = getDecryptionKey(keyId);
|
||||||
if (decryptionKeys == null) {
|
if (decryptionKeys == null) {
|
||||||
LOGGER.debug("Skipping PKESK because no matching key " + KeyIdUtil.formatKeyId(keyId) + " was provided");
|
LOGGER.debug("Skipping PKESK because no matching key " + KeyIdUtil.formatKeyId(keyId) + " was provided");
|
||||||
|
@ -508,13 +508,8 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
}
|
}
|
||||||
PGPSecretKey secretKey = decryptionKeys.getSecretKey(keyId);
|
PGPSecretKey secretKey = decryptionKeys.getSecretKey(keyId);
|
||||||
SubkeyIdentifier decryptionKeyId = new SubkeyIdentifier(decryptionKeys, secretKey.getKeyID());
|
SubkeyIdentifier decryptionKeyId = new SubkeyIdentifier(decryptionKeys, secretKey.getKeyID());
|
||||||
S2K s2K = secretKey.getS2K();
|
if (hasUnsupportedS2KSpecifier(secretKey, decryptionKeyId)) {
|
||||||
if (s2K != null) {
|
continue;
|
||||||
int s2kType = s2K.getType();
|
|
||||||
if (s2kType >= 100 && s2kType <= 110) {
|
|
||||||
LOGGER.debug("Skipping PKESK because key " + decryptionKeyId + " has unsupported private S2K specifier " + s2kType);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
LOGGER.debug("Attempt decryption using secret key " + decryptionKeyId);
|
LOGGER.debug("Attempt decryption using secret key " + decryptionKeyId);
|
||||||
|
|
||||||
|
@ -527,10 +522,7 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
}
|
}
|
||||||
|
|
||||||
PGPPrivateKey privateKey = UnlockSecretKey.unlockSecretKey(secretKey, protector);
|
PGPPrivateKey privateKey = UnlockSecretKey.unlockSecretKey(secretKey, protector);
|
||||||
|
if (decryptWithPrivateKey(privateKey, decryptionKeyId, pkesk)) {
|
||||||
PublicKeyDataDecryptorFactory decryptorFactory = ImplementationFactory.getInstance()
|
|
||||||
.getPublicKeyDataDecryptorFactory(privateKey);
|
|
||||||
if (decryptPKESKAndStream(decryptionKeyId, decryptorFactory, pkesk)) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -541,13 +533,8 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
PGPSecretKeyRing decryptionKeys = decryptionKeyCandidate.getA();
|
PGPSecretKeyRing decryptionKeys = decryptionKeyCandidate.getA();
|
||||||
PGPSecretKey secretKey = decryptionKeyCandidate.getB();
|
PGPSecretKey secretKey = decryptionKeyCandidate.getB();
|
||||||
SubkeyIdentifier decryptionKeyId = new SubkeyIdentifier(decryptionKeys, secretKey.getKeyID());
|
SubkeyIdentifier decryptionKeyId = new SubkeyIdentifier(decryptionKeys, secretKey.getKeyID());
|
||||||
S2K s2K = secretKey.getS2K();
|
if (hasUnsupportedS2KSpecifier(secretKey, decryptionKeyId)) {
|
||||||
if (s2K != null) {
|
continue;
|
||||||
int s2kType = s2K.getType();
|
|
||||||
if (s2kType >= 100 && s2kType <= 110) {
|
|
||||||
LOGGER.debug("Skipping PKESK because key " + decryptionKeyId + " has unsupported private S2K specifier " + s2kType);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
LOGGER.debug("Attempt decryption of anonymous PKESK with key " + decryptionKeyId);
|
LOGGER.debug("Attempt decryption of anonymous PKESK with key " + decryptionKeyId);
|
||||||
SecretKeyRingProtector protector = options.getSecretKeyProtector(decryptionKeyCandidate.getA());
|
SecretKeyRingProtector protector = options.getSecretKeyProtector(decryptionKeyCandidate.getA());
|
||||||
|
@ -556,11 +543,9 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
postponedDueToMissingPassphrase.add(new Tuple<>(secretKey, pkesk));
|
postponedDueToMissingPassphrase.add(new Tuple<>(secretKey, pkesk));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
PGPPrivateKey privateKey = UnlockSecretKey.unlockSecretKey(decryptionKeyCandidate.getB(), protector);
|
|
||||||
PublicKeyDataDecryptorFactory decryptorFactory = ImplementationFactory.getInstance()
|
|
||||||
.getPublicKeyDataDecryptorFactory(privateKey);
|
|
||||||
|
|
||||||
if (decryptPKESKAndStream(decryptionKeyId, decryptorFactory, pkesk)) {
|
PGPPrivateKey privateKey = UnlockSecretKey.unlockSecretKey(secretKey, protector);
|
||||||
|
if (decryptWithPrivateKey(privateKey, decryptionKeyId, pkesk)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -571,7 +556,8 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
Set<SubkeyIdentifier> keyIds = new HashSet<>();
|
Set<SubkeyIdentifier> keyIds = new HashSet<>();
|
||||||
for (Tuple<PGPSecretKey, PGPPublicKeyEncryptedData> k : postponedDueToMissingPassphrase) {
|
for (Tuple<PGPSecretKey, PGPPublicKeyEncryptedData> k : postponedDueToMissingPassphrase) {
|
||||||
PGPSecretKey key = k.getA();
|
PGPSecretKey key = k.getA();
|
||||||
keyIds.add(new SubkeyIdentifier(getDecryptionKey(key.getKeyID()), key.getKeyID()));
|
PGPSecretKeyRing keys = getDecryptionKey(key.getKeyID());
|
||||||
|
keyIds.add(new SubkeyIdentifier(keys, key.getKeyID()));
|
||||||
}
|
}
|
||||||
if (!keyIds.isEmpty()) {
|
if (!keyIds.isEmpty()) {
|
||||||
throw new MissingPassphraseException(keyIds);
|
throw new MissingPassphraseException(keyIds);
|
||||||
|
@ -584,21 +570,14 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
long keyId = secretKey.getKeyID();
|
long keyId = secretKey.getKeyID();
|
||||||
PGPSecretKeyRing decryptionKey = getDecryptionKey(keyId);
|
PGPSecretKeyRing decryptionKey = getDecryptionKey(keyId);
|
||||||
SubkeyIdentifier decryptionKeyId = new SubkeyIdentifier(decryptionKey, keyId);
|
SubkeyIdentifier decryptionKeyId = new SubkeyIdentifier(decryptionKey, keyId);
|
||||||
S2K s2K = secretKey.getS2K();
|
if (hasUnsupportedS2KSpecifier(secretKey, decryptionKeyId)) {
|
||||||
if (s2K != null) {
|
continue;
|
||||||
int s2kType = s2K.getType();
|
|
||||||
if (s2kType >= 100 && s2kType <= 110) {
|
|
||||||
LOGGER.debug("Skipping PKESK because key " + decryptionKeyId + " has unsupported private S2K specifier " + s2kType);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGGER.debug("Attempt decryption with key " + decryptionKeyId + " while interactively requesting its passphrase");
|
LOGGER.debug("Attempt decryption with key " + decryptionKeyId + " while interactively requesting its passphrase");
|
||||||
SecretKeyRingProtector protector = options.getSecretKeyProtector(decryptionKey);
|
SecretKeyRingProtector protector = options.getSecretKeyProtector(decryptionKey);
|
||||||
PGPPrivateKey privateKey = UnlockSecretKey.unlockSecretKey(secretKey, protector.getDecryptor(keyId));
|
PGPPrivateKey privateKey = UnlockSecretKey.unlockSecretKey(secretKey, protector);
|
||||||
PublicKeyDataDecryptorFactory decryptorFactory = ImplementationFactory.getInstance()
|
if (decryptWithPrivateKey(privateKey, decryptionKeyId, pkesk)) {
|
||||||
.getPublicKeyDataDecryptorFactory(privateKey);
|
|
||||||
|
|
||||||
if (decryptPKESKAndStream(decryptionKeyId, decryptorFactory, pkesk)) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -613,6 +592,27 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean decryptWithPrivateKey(PGPPrivateKey privateKey,
|
||||||
|
SubkeyIdentifier decryptionKeyId,
|
||||||
|
PGPPublicKeyEncryptedData pkesk)
|
||||||
|
throws PGPException, IOException {
|
||||||
|
PublicKeyDataDecryptorFactory decryptorFactory = ImplementationFactory.getInstance()
|
||||||
|
.getPublicKeyDataDecryptorFactory(privateKey);
|
||||||
|
return decryptPKESKAndStream(decryptionKeyId, decryptorFactory, pkesk);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean hasUnsupportedS2KSpecifier(PGPSecretKey secretKey, SubkeyIdentifier decryptionKeyId) {
|
||||||
|
S2K s2K = secretKey.getS2K();
|
||||||
|
if (s2K != null) {
|
||||||
|
int s2kType = s2K.getType();
|
||||||
|
if (s2kType >= 100 && s2kType <= 110) {
|
||||||
|
LOGGER.debug("Skipping PKESK because key " + decryptionKeyId + " has unsupported private S2K specifier " + s2kType);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean decryptSKESKAndStream(PGPPBEEncryptedData skesk, PBEDataDecryptorFactory decryptorFactory)
|
private boolean decryptSKESKAndStream(PGPPBEEncryptedData skesk, PBEDataDecryptorFactory decryptorFactory)
|
||||||
throws IOException, UnacceptableAlgorithmException {
|
throws IOException, UnacceptableAlgorithmException {
|
||||||
try {
|
try {
|
||||||
|
@ -661,14 +661,6 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PGPSecretKey getDecryptionKey(PGPSecretKeyRing decryptionKeys, long keyId) {
|
|
||||||
KeyRingInfo info = PGPainless.inspectKeyRing(decryptionKeys);
|
|
||||||
if (info.getEncryptionSubkeys(EncryptionPurpose.ANY).contains(info.getPublicKey(keyId))) {
|
|
||||||
return info.getSecretKey(keyId);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void throwIfUnacceptable(SymmetricKeyAlgorithm algorithm)
|
private void throwIfUnacceptable(SymmetricKeyAlgorithm algorithm)
|
||||||
throws UnacceptableAlgorithmException {
|
throws UnacceptableAlgorithmException {
|
||||||
if (!policy.getSymmetricKeyDecryptionAlgorithmPolicy().isAcceptable(algorithm)) {
|
if (!policy.getSymmetricKeyDecryptionAlgorithmPolicy().isAcceptable(algorithm)) {
|
||||||
|
@ -883,20 +875,6 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
return resultBuilder.build();
|
return resultBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void log(String message) {
|
|
||||||
LOGGER.debug(message);
|
|
||||||
// CHECKSTYLE:OFF
|
|
||||||
System.out.println(message);
|
|
||||||
// CHECKSTYLE:ON
|
|
||||||
}
|
|
||||||
|
|
||||||
static void log(String message, Throwable e) {
|
|
||||||
log(message);
|
|
||||||
// CHECKSTYLE:OFF
|
|
||||||
e.printStackTrace();
|
|
||||||
// CHECKSTYLE:ON
|
|
||||||
}
|
|
||||||
|
|
||||||
// In 'OPS LIT("Foo") SIG', OPS is only updated with "Foo"
|
// In 'OPS LIT("Foo") SIG', OPS is only updated with "Foo"
|
||||||
// In 'OPS[1] OPS LIT("Foo") SIG SIG', OPS[1] (nested) is updated with OPS LIT("Foo") SIG.
|
// In 'OPS[1] OPS LIT("Foo") SIG SIG', OPS[1] (nested) is updated with OPS LIT("Foo") SIG.
|
||||||
// Therefore, we need to handle the innermost signature layer differently when updating with Literal data.
|
// Therefore, we need to handle the innermost signature layer differently when updating with Literal data.
|
||||||
|
@ -1004,7 +982,7 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
SignatureValidator.signatureWasCreatedInBounds(options.getVerifyNotBefore(), options.getVerifyNotAfter())
|
SignatureValidator.signatureWasCreatedInBounds(options.getVerifyNotBefore(), options.getVerifyNotAfter())
|
||||||
.verify(signature);
|
.verify(signature);
|
||||||
CertificateValidator.validateCertificateAndVerifyOnePassSignature(onePassSignature, policy);
|
CertificateValidator.validateCertificateAndVerifyOnePassSignature(onePassSignature, policy);
|
||||||
LOGGER.debug("Acceptable signature by key " + verification.getSigningKey());
|
LOGGER.debug("Acceptable signature by key " + verification.getSigningKey());
|
||||||
layer.addVerifiedOnePassSignature(verification);
|
layer.addVerifiedOnePassSignature(verification);
|
||||||
|
|
Loading…
Reference in a new issue