2018-06-13 17:26:48 +02:00
/ *
* Copyright 2018 Paul Schaub .
*
* Licensed under the Apache License , Version 2 . 0 ( the " License " ) ;
* you may not use this file except in compliance with the License .
* You may obtain a copy of the License at
*
* http : //www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing , software
* distributed under the License is distributed on an " AS IS " BASIS ,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
* See the License for the specific language governing permissions and
* limitations under the License .
* /
2018-07-18 18:23:06 +02:00
package org.pgpainless.decryption_verification ;
2018-06-06 18:46:41 +02:00
2021-06-15 17:35:58 +02:00
import java.io.BufferedInputStream ;
2021-07-15 16:55:13 +02:00
import java.io.EOFException ;
2018-06-06 18:46:41 +02:00
import java.io.IOException ;
import java.io.InputStream ;
2021-02-17 21:04:05 +01:00
import java.util.ArrayList ;
2018-06-06 18:46:41 +02:00
import java.util.HashMap ;
import java.util.Iterator ;
2020-08-24 14:55:06 +02:00
import java.util.List ;
2018-06-06 18:46:41 +02:00
import java.util.Map ;
2018-06-19 17:14:37 +02:00
import java.util.logging.Level ;
import java.util.logging.Logger ;
2020-12-27 01:56:18 +01:00
import javax.annotation.Nonnull ;
2018-06-06 18:46:41 +02:00
import org.bouncycastle.openpgp.PGPCompressedData ;
2020-12-26 19:04:27 +01:00
import org.bouncycastle.openpgp.PGPEncryptedData ;
2018-06-06 18:46:41 +02:00
import org.bouncycastle.openpgp.PGPEncryptedDataList ;
import org.bouncycastle.openpgp.PGPException ;
import org.bouncycastle.openpgp.PGPLiteralData ;
import org.bouncycastle.openpgp.PGPObjectFactory ;
import org.bouncycastle.openpgp.PGPOnePassSignature ;
import org.bouncycastle.openpgp.PGPOnePassSignatureList ;
2020-12-26 19:04:27 +01:00
import org.bouncycastle.openpgp.PGPPBEEncryptedData ;
2018-06-06 18:46:41 +02:00
import org.bouncycastle.openpgp.PGPPrivateKey ;
import org.bouncycastle.openpgp.PGPPublicKey ;
import org.bouncycastle.openpgp.PGPPublicKeyEncryptedData ;
import org.bouncycastle.openpgp.PGPPublicKeyRing ;
import org.bouncycastle.openpgp.PGPSecretKey ;
2021-01-09 16:16:17 +01:00
import org.bouncycastle.openpgp.PGPSecretKeyRing ;
2020-08-24 14:55:06 +02:00
import org.bouncycastle.openpgp.PGPSignature ;
2018-06-06 18:46:41 +02:00
import org.bouncycastle.openpgp.PGPUtil ;
import org.bouncycastle.openpgp.operator.KeyFingerPrintCalculator ;
2020-12-26 19:04:27 +01:00
import org.bouncycastle.openpgp.operator.PBEDataDecryptorFactory ;
2018-06-06 18:46:41 +02:00
import org.bouncycastle.openpgp.operator.PGPContentVerifierBuilderProvider ;
import org.bouncycastle.openpgp.operator.PublicKeyDataDecryptorFactory ;
2021-05-17 13:47:46 +02:00
import org.pgpainless.PGPainless ;
2018-07-18 18:23:06 +02:00
import org.pgpainless.algorithm.CompressionAlgorithm ;
2021-06-15 17:08:40 +02:00
import org.pgpainless.algorithm.EncryptionPurpose ;
2021-04-25 00:28:48 +02:00
import org.pgpainless.algorithm.StreamEncoding ;
2018-07-18 18:23:06 +02:00
import org.pgpainless.algorithm.SymmetricKeyAlgorithm ;
2021-04-27 12:27:25 +02:00
import org.pgpainless.exception.MessageNotIntegrityProtectedException ;
2021-05-28 23:20:25 +02:00
import org.pgpainless.exception.MissingDecryptionMethodException ;
2021-06-15 17:35:58 +02:00
import org.pgpainless.exception.MissingLiteralDataException ;
2021-05-17 13:47:46 +02:00
import org.pgpainless.exception.UnacceptableAlgorithmException ;
2020-12-27 01:56:18 +01:00
import org.pgpainless.implementation.ImplementationFactory ;
2018-07-18 18:23:06 +02:00
import org.pgpainless.key.OpenPgpV4Fingerprint ;
2021-04-26 13:38:12 +02:00
import org.pgpainless.key.SubkeyIdentifier ;
2021-06-15 17:08:40 +02:00
import org.pgpainless.key.info.KeyRingInfo ;
2021-05-14 13:18:34 +02:00
import org.pgpainless.key.protection.UnlockSecretKey ;
2021-04-26 13:38:12 +02:00
import org.pgpainless.signature.DetachedSignature ;
import org.pgpainless.signature.OnePassSignature ;
2021-02-17 21:04:05 +01:00
import org.pgpainless.util.IntegrityProtectedInputStream ;
2020-12-26 19:04:27 +01:00
import org.pgpainless.util.Passphrase ;
2018-06-06 18:46:41 +02:00
2018-07-02 21:40:59 +02:00
public final class DecryptionStreamFactory {
2018-06-06 18:46:41 +02:00
2018-06-19 17:14:37 +02:00
private static final Logger LOGGER = Logger . getLogger ( DecryptionStreamFactory . class . getName ( ) ) ;
2018-06-21 15:19:07 +02:00
private static final Level LEVEL = Level . FINE ;
2021-02-19 21:37:54 +01:00
private static final int MAX_RECURSION_DEPTH = 16 ;
2018-06-19 17:14:37 +02:00
2021-06-15 17:08:40 +02:00
private final ConsumerOptions options ;
2018-06-06 18:46:41 +02:00
2018-07-23 16:23:23 +02:00
private final OpenPgpMetadata . Builder resultBuilder = OpenPgpMetadata . getBuilder ( ) ;
2021-07-15 16:55:13 +02:00
private static final PGPContentVerifierBuilderProvider verifierBuilderProvider =
ImplementationFactory . getInstance ( ) . getPGPContentVerifierBuilderProvider ( ) ;
private static final KeyFingerPrintCalculator keyFingerprintCalculator =
ImplementationFactory . getInstance ( ) . getKeyFingerprintCalculator ( ) ;
2020-08-24 14:55:06 +02:00
private final Map < OpenPgpV4Fingerprint , OnePassSignature > verifiableOnePassSignatures = new HashMap < > ( ) ;
2021-02-17 21:04:05 +01:00
private final List < IntegrityProtectedInputStream > integrityProtectedStreams = new ArrayList < > ( ) ;
2018-06-06 18:46:41 +02:00
2021-06-15 17:08:40 +02:00
public DecryptionStreamFactory ( ConsumerOptions options ) {
this . options = options ;
2018-06-06 18:46:41 +02:00
}
2018-07-31 20:09:16 +02:00
public static DecryptionStream create ( @Nonnull InputStream inputStream ,
2021-06-15 17:56:36 +02:00
@Nonnull ConsumerOptions options )
throws PGPException , IOException {
2021-06-15 17:35:58 +02:00
BufferedInputStream bufferedIn = new BufferedInputStream ( inputStream ) ;
bufferedIn . mark ( 200 ) ;
2021-06-15 17:08:40 +02:00
DecryptionStreamFactory factory = new DecryptionStreamFactory ( options ) ;
for ( PGPSignature signature : options . getDetachedSignatures ( ) ) {
PGPPublicKeyRing signingKeyRing = factory . findSignatureVerificationKeyRing ( signature . getKeyID ( ) ) ;
if ( signingKeyRing = = null ) {
continue ;
2020-08-24 14:55:06 +02:00
}
2021-06-15 17:08:40 +02:00
PGPPublicKey signingKey = signingKeyRing . getPublicKey ( signature . getKeyID ( ) ) ;
signature . init ( ImplementationFactory . getInstance ( ) . getPGPContentVerifierBuilderProvider ( ) , signingKey ) ;
factory . resultBuilder . addDetachedSignature (
new DetachedSignature ( signature , signingKeyRing , new SubkeyIdentifier ( signingKeyRing , signature . getKeyID ( ) ) ) ) ;
2020-08-24 14:55:06 +02:00
}
2021-06-15 17:08:40 +02:00
PGPObjectFactory objectFactory = new PGPObjectFactory (
2021-06-15 17:35:58 +02:00
PGPUtil . getDecoderStream ( bufferedIn ) , keyFingerprintCalculator ) ;
2021-06-15 17:08:40 +02:00
2021-06-15 17:35:58 +02:00
try {
// Parse OpenPGP message
inputStream = factory . processPGPPackets ( objectFactory , 1 ) ;
2021-07-15 16:55:13 +02:00
} catch ( EOFException e ) {
throw e ;
}
catch ( MissingLiteralDataException e ) {
// Not an OpenPGP message.
// Reset the buffered stream to parse the message as arbitrary binary data
2021-06-15 17:35:58 +02:00
// to allow for detached signature verification.
bufferedIn . reset ( ) ;
inputStream = bufferedIn ;
2021-07-15 16:55:13 +02:00
} catch ( IOException e ) {
if ( e . getMessage ( ) . contains ( " invalid armor " ) ) {
// We falsely assumed the data to be armored.
bufferedIn . reset ( ) ;
inputStream = bufferedIn ;
} else {
throw e ;
}
2021-06-15 17:35:58 +02:00
}
return new DecryptionStream ( inputStream , factory . resultBuilder , factory . integrityProtectedStreams ) ;
2018-06-06 18:46:41 +02:00
}
2021-02-19 21:37:54 +01:00
private InputStream processPGPPackets ( @Nonnull PGPObjectFactory objectFactory , int depth ) throws IOException , PGPException {
if ( depth > = MAX_RECURSION_DEPTH ) {
throw new PGPException ( " Maximum recursion depth of packages exceeded. " ) ;
}
2020-01-10 17:12:13 +01:00
Object nextPgpObject ;
while ( ( nextPgpObject = objectFactory . nextObject ( ) ) ! = null ) {
if ( nextPgpObject instanceof PGPEncryptedDataList ) {
2021-02-19 21:37:54 +01:00
return processPGPEncryptedDataList ( ( PGPEncryptedDataList ) nextPgpObject , depth ) ;
2018-06-06 18:46:41 +02:00
}
2020-01-10 17:12:13 +01:00
if ( nextPgpObject instanceof PGPCompressedData ) {
2021-02-19 21:37:54 +01:00
return processPGPCompressedData ( ( PGPCompressedData ) nextPgpObject , depth ) ;
2018-06-06 18:46:41 +02:00
}
2020-01-10 17:12:13 +01:00
if ( nextPgpObject instanceof PGPOnePassSignatureList ) {
2021-02-19 21:37:54 +01:00
return processOnePassSignatureList ( objectFactory , ( PGPOnePassSignatureList ) nextPgpObject , depth ) ;
2018-06-06 18:46:41 +02:00
}
2020-01-10 17:12:13 +01:00
if ( nextPgpObject instanceof PGPLiteralData ) {
return processPGPLiteralData ( objectFactory , ( PGPLiteralData ) nextPgpObject ) ;
}
}
2018-06-06 18:46:41 +02:00
2021-06-15 17:35:58 +02:00
throw new MissingLiteralDataException ( " No Literal Data Packet found " ) ;
2020-01-10 17:12:13 +01:00
}
2018-06-06 18:46:41 +02:00
2021-02-19 21:37:54 +01:00
private InputStream processPGPEncryptedDataList ( PGPEncryptedDataList pgpEncryptedDataList , int depth )
2020-01-10 17:12:13 +01:00
throws PGPException , IOException {
LOGGER . log ( LEVEL , " Encountered PGPEncryptedDataList " ) ;
InputStream decryptedDataStream = decrypt ( pgpEncryptedDataList ) ;
2021-07-15 16:55:13 +02:00
InputStream decodedDataStream = PGPUtil . getDecoderStream ( decryptedDataStream ) ;
PGPObjectFactory factory = new PGPObjectFactory ( decodedDataStream , keyFingerprintCalculator ) ;
return processPGPPackets ( factory , + + depth ) ;
2020-01-10 17:12:13 +01:00
}
2018-06-06 18:46:41 +02:00
2021-02-19 21:37:54 +01:00
private InputStream processPGPCompressedData ( PGPCompressedData pgpCompressedData , int depth )
2020-01-10 17:12:13 +01:00
throws PGPException , IOException {
CompressionAlgorithm compressionAlgorithm = CompressionAlgorithm . fromId ( pgpCompressedData . getAlgorithm ( ) ) ;
LOGGER . log ( LEVEL , " Encountered PGPCompressedData: " + compressionAlgorithm ) ;
resultBuilder . setCompressionAlgorithm ( compressionAlgorithm ) ;
2021-07-15 16:55:13 +02:00
InputStream inflatedDataStream = pgpCompressedData . getDataStream ( ) ;
InputStream decodedDataStream = PGPUtil . getDecoderStream ( inflatedDataStream ) ;
PGPObjectFactory objectFactory = new PGPObjectFactory ( decodedDataStream , keyFingerprintCalculator ) ;
2020-01-10 17:12:13 +01:00
2021-02-19 21:37:54 +01:00
return processPGPPackets ( objectFactory , + + depth ) ;
2020-01-10 17:12:13 +01:00
}
2021-02-19 21:37:54 +01:00
private InputStream processOnePassSignatureList ( @Nonnull PGPObjectFactory objectFactory , PGPOnePassSignatureList onePassSignatures , int depth )
2020-01-10 17:12:13 +01:00
throws PGPException , IOException {
LOGGER . log ( LEVEL , " Encountered PGPOnePassSignatureList of size " + onePassSignatures . size ( ) ) ;
initOnePassSignatures ( onePassSignatures ) ;
2021-02-19 21:37:54 +01:00
return processPGPPackets ( objectFactory , + + depth ) ;
2020-01-10 17:12:13 +01:00
}
private InputStream processPGPLiteralData ( @Nonnull PGPObjectFactory objectFactory , PGPLiteralData pgpLiteralData ) {
LOGGER . log ( LEVEL , " Found PGPLiteralData " ) ;
InputStream literalDataInputStream = pgpLiteralData . getInputStream ( ) ;
2021-07-15 16:55:13 +02:00
resultBuilder . setFileName ( pgpLiteralData . getFileName ( ) )
. setModificationDate ( pgpLiteralData . getModificationTime ( ) )
. setFileEncoding ( StreamEncoding . fromCode ( pgpLiteralData . getFormat ( ) ) ) ;
2020-01-10 17:12:13 +01:00
if ( verifiableOnePassSignatures . isEmpty ( ) ) {
LOGGER . log ( LEVEL , " No OnePassSignatures found -> We are done " ) ;
return literalDataInputStream ;
2018-06-06 18:46:41 +02:00
}
2020-01-10 17:12:13 +01:00
return new SignatureVerifyingInputStream ( literalDataInputStream ,
objectFactory , verifiableOnePassSignatures , resultBuilder ) ;
2018-06-06 18:46:41 +02:00
}
2018-07-31 20:09:16 +02:00
private InputStream decrypt ( @Nonnull PGPEncryptedDataList encryptedDataList )
2018-06-06 18:46:41 +02:00
throws PGPException {
2020-12-26 19:04:27 +01:00
Iterator < PGPEncryptedData > encryptedDataIterator = encryptedDataList . getEncryptedDataObjects ( ) ;
2020-01-10 17:12:13 +01:00
if ( ! encryptedDataIterator . hasNext ( ) ) {
2018-06-19 17:14:37 +02:00
throw new PGPException ( " Decryption failed - EncryptedDataList has no items " ) ;
2018-06-06 18:46:41 +02:00
}
PGPPrivateKey decryptionKey = null ;
PGPPublicKeyEncryptedData encryptedSessionKey = null ;
2020-01-10 17:12:13 +01:00
while ( encryptedDataIterator . hasNext ( ) ) {
2020-12-26 19:04:27 +01:00
PGPEncryptedData encryptedData = encryptedDataIterator . next ( ) ;
2021-06-15 17:08:40 +02:00
// TODO: Can we just skip non-integrity-protected packages?
2021-04-27 12:27:25 +02:00
if ( ! encryptedData . isIntegrityProtected ( ) ) {
throw new MessageNotIntegrityProtectedException ( ) ;
}
2021-06-15 17:08:40 +02:00
2021-05-14 13:18:34 +02:00
// Data is passphrase encrypted
2021-04-27 12:27:25 +02:00
if ( encryptedData instanceof PGPPBEEncryptedData ) {
2020-12-26 19:04:27 +01:00
PGPPBEEncryptedData pbeEncryptedData = ( PGPPBEEncryptedData ) encryptedData ;
2021-06-15 17:08:40 +02:00
for ( Passphrase passphrase : options . getDecryptionPassphrases ( ) ) {
2020-12-27 01:56:18 +01:00
PBEDataDecryptorFactory passphraseDecryptor = ImplementationFactory . getInstance ( )
2021-06-15 17:08:40 +02:00
. getPBEDataDecryptorFactory ( passphrase ) ;
2020-12-26 23:36:33 +01:00
try {
2021-06-15 17:08:40 +02:00
InputStream decryptedDataStream = pbeEncryptedData . getDataStream ( passphraseDecryptor ) ;
SymmetricKeyAlgorithm symmetricKeyAlgorithm = SymmetricKeyAlgorithm . fromId (
pbeEncryptedData . getSymmetricAlgorithm ( passphraseDecryptor ) ) ;
throwIfAlgorithmIsRejected ( symmetricKeyAlgorithm ) ;
resultBuilder . setSymmetricKeyAlgorithm ( symmetricKeyAlgorithm ) ;
return decryptedDataStream ;
2020-12-26 23:36:33 +01:00
} catch ( PGPException e ) {
LOGGER . log ( LEVEL , " Probable passphrase mismatch, skip PBE encrypted data block " , e ) ;
}
2020-12-26 19:04:27 +01:00
}
2021-05-14 13:18:34 +02:00
}
2021-06-15 17:08:40 +02:00
2021-05-14 13:18:34 +02:00
// data is public key encrypted
else if ( encryptedData instanceof PGPPublicKeyEncryptedData ) {
2020-12-26 19:04:27 +01:00
PGPPublicKeyEncryptedData publicKeyEncryptedData = ( PGPPublicKeyEncryptedData ) encryptedData ;
long keyId = publicKeyEncryptedData . getKeyID ( ) ;
2021-06-15 17:08:40 +02:00
if ( ! options . getDecryptionKeys ( ) . isEmpty ( ) ) {
2021-01-09 16:16:17 +01:00
// Known key id
if ( keyId ! = 0 ) {
LOGGER . log ( LEVEL , " PGPEncryptedData is encrypted for key " + Long . toHexString ( keyId ) ) ;
resultBuilder . addRecipientKeyId ( keyId ) ;
2021-06-15 17:08:40 +02:00
PGPSecretKeyRing decryptionKeyRing = findDecryptionKeyRing ( keyId ) ;
if ( decryptionKeyRing ! = null ) {
PGPSecretKey secretKey = decryptionKeyRing . getSecretKey ( keyId ) ;
2021-01-09 16:16:17 +01:00
LOGGER . log ( LEVEL , " Found respective secret key " + Long . toHexString ( keyId ) ) ;
// Watch out! This assignment is possibly done multiple times.
encryptedSessionKey = publicKeyEncryptedData ;
2021-06-15 17:08:40 +02:00
decryptionKey = UnlockSecretKey . unlockSecretKey ( secretKey , options . getSecretKeyProtector ( decryptionKeyRing ) ) ;
2021-07-04 13:08:24 +02:00
resultBuilder . setDecryptionKey ( new SubkeyIdentifier ( decryptionKeyRing , decryptionKey . getKeyID ( ) ) ) ;
2021-01-09 16:16:17 +01:00
}
2021-06-15 17:08:40 +02:00
}
// Hidden recipient
else {
2021-01-09 16:16:17 +01:00
LOGGER . log ( LEVEL , " Hidden recipient detected. Try to decrypt with all available secret keys. " ) ;
2021-06-15 17:08:40 +02:00
outerloop : for ( PGPSecretKeyRing ring : options . getDecryptionKeys ( ) ) {
KeyRingInfo info = new KeyRingInfo ( ring ) ;
List < PGPPublicKey > encryptionSubkeys = info . getEncryptionSubkeys ( EncryptionPurpose . STORAGE_AND_COMMUNICATIONS ) ;
for ( PGPPublicKey pubkey : encryptionSubkeys ) {
PGPSecretKey key = ring . getSecretKey ( pubkey . getKeyID ( ) ) ;
if ( key = = null ) {
continue ;
}
PGPPrivateKey privateKey = UnlockSecretKey . unlockSecretKey ( key , options . getSecretKeyProtector ( ring ) . getDecryptor ( key . getKeyID ( ) ) ) ;
2021-01-09 16:16:17 +01:00
PublicKeyDataDecryptorFactory decryptorFactory = ImplementationFactory . getInstance ( ) . getPublicKeyDataDecryptorFactory ( privateKey ) ;
try {
publicKeyEncryptedData . getSymmetricAlgorithm ( decryptorFactory ) ; // will only succeed if we have the right secret key
LOGGER . log ( LEVEL , " Found correct key " + Long . toHexString ( key . getKeyID ( ) ) + " for hidden recipient decryption. " ) ;
decryptionKey = privateKey ;
2021-07-04 13:08:24 +02:00
resultBuilder . setDecryptionKey ( new SubkeyIdentifier ( ring , decryptionKey . getKeyID ( ) ) ) ;
2021-01-09 16:16:17 +01:00
encryptedSessionKey = publicKeyEncryptedData ;
break outerloop ;
2021-02-17 20:20:10 +01:00
} catch ( PGPException | ClassCastException e ) {
2021-01-09 16:16:17 +01:00
LOGGER . log ( LEVEL , " Skipping wrong key " + Long . toHexString ( key . getKeyID ( ) ) + " for hidden recipient decryption. " , e ) ;
}
}
}
2020-12-26 19:04:27 +01:00
}
}
2018-06-06 18:46:41 +02:00
}
}
2021-06-15 17:08:40 +02:00
return decryptWith ( encryptedSessionKey , decryptionKey ) ;
}
2018-06-06 18:46:41 +02:00
2021-06-15 17:08:40 +02:00
private InputStream decryptWith ( PGPPublicKeyEncryptedData encryptedSessionKey , PGPPrivateKey decryptionKey )
throws PGPException {
2018-06-06 18:46:41 +02:00
if ( decryptionKey = = null ) {
2021-05-28 23:20:25 +02:00
throw new MissingDecryptionMethodException ( " Decryption failed - No suitable decryption key or passphrase found " ) ;
2018-06-06 18:46:41 +02:00
}
2021-02-17 21:04:05 +01:00
PublicKeyDataDecryptorFactory dataDecryptor = ImplementationFactory . getInstance ( )
2020-12-27 01:56:18 +01:00
. getPublicKeyDataDecryptorFactory ( decryptionKey ) ;
2020-12-26 19:04:27 +01:00
2018-06-19 17:14:37 +02:00
SymmetricKeyAlgorithm symmetricKeyAlgorithm = SymmetricKeyAlgorithm
2021-02-17 21:04:05 +01:00
. fromId ( encryptedSessionKey . getSymmetricAlgorithm ( dataDecryptor ) ) ;
2021-02-17 20:07:54 +01:00
if ( symmetricKeyAlgorithm = = SymmetricKeyAlgorithm . NULL ) {
2021-05-17 13:47:46 +02:00
LOGGER . log ( LEVEL , " Message is unencrypted " ) ;
} else {
LOGGER . log ( LEVEL , " Message is encrypted using " + symmetricKeyAlgorithm ) ;
2021-02-17 20:07:54 +01:00
}
2021-05-17 13:47:46 +02:00
throwIfAlgorithmIsRejected ( symmetricKeyAlgorithm ) ;
2018-06-19 17:14:37 +02:00
resultBuilder . setSymmetricKeyAlgorithm ( symmetricKeyAlgorithm ) ;
2021-05-17 13:47:46 +02:00
IntegrityProtectedInputStream integrityProtected =
new IntegrityProtectedInputStream ( encryptedSessionKey . getDataStream ( dataDecryptor ) , encryptedSessionKey ) ;
integrityProtectedStreams . add ( integrityProtected ) ;
return integrityProtected ;
}
private void throwIfAlgorithmIsRejected ( SymmetricKeyAlgorithm algorithm ) throws UnacceptableAlgorithmException {
if ( ! PGPainless . getPolicy ( ) . getSymmetricKeyDecryptionAlgoritmPolicy ( ) . isAcceptable ( algorithm ) ) {
throw new UnacceptableAlgorithmException ( " Data is "
+ ( algorithm = = SymmetricKeyAlgorithm . NULL ? " unencrypted " : " encrypted with symmetric algorithm " + algorithm ) + " which is not acceptable as per PGPainless' policy. \ n " +
" To mark this algorithm as acceptable, use PGPainless.getPolicy().setSymmetricKeyDecryptionAlgorithmPolicy(). " ) ;
2021-02-17 21:04:05 +01:00
}
2018-06-06 18:46:41 +02:00
}
2018-07-31 20:09:16 +02:00
private void initOnePassSignatures ( @Nonnull PGPOnePassSignatureList onePassSignatureList ) throws PGPException {
2018-06-06 18:46:41 +02:00
Iterator < PGPOnePassSignature > iterator = onePassSignatureList . iterator ( ) ;
if ( ! iterator . hasNext ( ) ) {
2018-06-19 17:14:37 +02:00
throw new PGPException ( " Verification failed - No OnePassSignatures found " ) ;
2018-06-06 18:46:41 +02:00
}
2020-01-10 15:12:04 +01:00
processOnePassSignatures ( iterator ) ;
}
private void processOnePassSignatures ( Iterator < PGPOnePassSignature > signatures ) throws PGPException {
while ( signatures . hasNext ( ) ) {
PGPOnePassSignature signature = signatures . next ( ) ;
2020-01-10 17:12:13 +01:00
processOnePassSignature ( signature ) ;
}
}
2018-06-06 18:46:41 +02:00
2020-01-10 17:12:13 +01:00
private void processOnePassSignature ( PGPOnePassSignature signature ) throws PGPException {
final long keyId = signature . getKeyID ( ) ;
2018-07-02 20:46:27 +02:00
2020-01-10 17:12:13 +01:00
LOGGER . log ( LEVEL , " Message contains OnePassSignature from " + Long . toHexString ( keyId ) ) ;
2018-07-02 20:46:27 +02:00
2020-01-10 17:12:13 +01:00
// Find public key
2021-04-26 13:38:12 +02:00
PGPPublicKeyRing verificationKeyRing = findSignatureVerificationKeyRing ( keyId ) ;
if ( verificationKeyRing = = null ) {
2020-08-24 14:55:06 +02:00
LOGGER . log ( LEVEL , " Missing verification key from " + Long . toHexString ( keyId ) ) ;
2020-01-10 17:12:13 +01:00
return ;
}
2021-04-26 13:38:12 +02:00
PGPPublicKey verificationKey = verificationKeyRing . getPublicKey ( keyId ) ;
2018-07-02 20:46:27 +02:00
2020-01-10 17:12:13 +01:00
signature . init ( verifierBuilderProvider , verificationKey ) ;
2020-12-27 01:56:18 +01:00
OpenPgpV4Fingerprint fingerprint = new OpenPgpV4Fingerprint ( verificationKey ) ;
2021-04-26 13:38:12 +02:00
OnePassSignature onePassSignature = new OnePassSignature ( signature , verificationKeyRing ) ;
2020-08-24 14:55:06 +02:00
resultBuilder . addOnePassSignature ( onePassSignature ) ;
2020-12-27 01:56:18 +01:00
verifiableOnePassSignatures . put ( fingerprint , onePassSignature ) ;
2020-01-10 17:12:13 +01:00
}
2018-07-02 20:46:27 +02:00
2021-06-15 17:08:40 +02:00
private PGPSecretKeyRing findDecryptionKeyRing ( long keyId ) {
for ( PGPSecretKeyRing key : options . getDecryptionKeys ( ) ) {
if ( key . getSecretKey ( keyId ) ! = null ) {
return key ;
}
}
return null ;
}
2021-04-26 13:38:12 +02:00
private PGPPublicKeyRing findSignatureVerificationKeyRing ( long keyId ) {
PGPPublicKeyRing verificationKeyRing = null ;
2021-06-15 17:08:40 +02:00
for ( PGPPublicKeyRing publicKeyRing : options . getCertificates ( ) ) {
2021-04-26 13:38:12 +02:00
PGPPublicKey verificationKey = publicKeyRing . getPublicKey ( keyId ) ;
2020-01-10 17:12:13 +01:00
if ( verificationKey ! = null ) {
LOGGER . log ( LEVEL , " Found public key " + Long . toHexString ( keyId ) + " for signature verification " ) ;
2021-04-26 13:38:12 +02:00
verificationKeyRing = publicKeyRing ;
2020-01-10 17:12:13 +01:00
break ;
2018-06-06 18:46:41 +02:00
}
2020-01-10 17:12:13 +01:00
}
2018-07-02 20:46:27 +02:00
2021-06-15 17:08:40 +02:00
if ( verificationKeyRing = = null & & options . getMissingCertificateCallback ( ) ! = null ) {
verificationKeyRing = options . getMissingCertificateCallback ( ) . onMissingPublicKeyEncountered ( keyId ) ;
2021-05-29 12:19:12 +02:00
}
2021-04-26 13:38:12 +02:00
return verificationKeyRing ;
2018-06-06 18:46:41 +02:00
}
}