2021-10-07 15:48:52 +02:00
// SPDX-FileCopyrightText: 2021 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
2021-04-26 13:38:12 +02:00
package org.pgpainless.signature.subpackets ;
import java.util.ArrayList ;
import java.util.Arrays ;
import java.util.Date ;
2021-05-25 13:52:45 +02:00
import java.util.LinkedHashSet ;
2021-04-26 13:38:12 +02:00
import java.util.List ;
2021-05-25 13:52:45 +02:00
import java.util.Set ;
2021-04-26 13:38:12 +02:00
2021-11-28 13:09:10 +01:00
import javax.annotation.Nonnull ;
2021-05-06 00:04:03 +02:00
import javax.annotation.Nullable ;
2021-04-26 13:38:12 +02:00
import org.bouncycastle.bcpg.sig.Exportable ;
import org.bouncycastle.bcpg.sig.Features ;
import org.bouncycastle.bcpg.sig.IntendedRecipientFingerprint ;
import org.bouncycastle.bcpg.sig.IssuerFingerprint ;
import org.bouncycastle.bcpg.sig.IssuerKeyID ;
import org.bouncycastle.bcpg.sig.KeyExpirationTime ;
import org.bouncycastle.bcpg.sig.KeyFlags ;
import org.bouncycastle.bcpg.sig.NotationData ;
import org.bouncycastle.bcpg.sig.PreferredAlgorithms ;
import org.bouncycastle.bcpg.sig.PrimaryUserID ;
import org.bouncycastle.bcpg.sig.Revocable ;
import org.bouncycastle.bcpg.sig.RevocationKey ;
import org.bouncycastle.bcpg.sig.RevocationReason ;
import org.bouncycastle.bcpg.sig.SignatureCreationTime ;
import org.bouncycastle.bcpg.sig.SignatureExpirationTime ;
import org.bouncycastle.bcpg.sig.SignatureTarget ;
import org.bouncycastle.bcpg.sig.SignerUserID ;
import org.bouncycastle.bcpg.sig.TrustSignature ;
import org.bouncycastle.openpgp.PGPException ;
import org.bouncycastle.openpgp.PGPPublicKey ;
import org.bouncycastle.openpgp.PGPSignature ;
import org.bouncycastle.openpgp.PGPSignatureList ;
import org.bouncycastle.openpgp.PGPSignatureSubpacketVector ;
import org.bouncycastle.util.encoders.Hex ;
2021-05-06 00:04:03 +02:00
import org.pgpainless.algorithm.CompressionAlgorithm ;
2021-10-04 13:32:04 +02:00
import org.pgpainless.algorithm.Feature ;
2021-05-06 00:04:03 +02:00
import org.pgpainless.algorithm.HashAlgorithm ;
import org.pgpainless.algorithm.KeyFlag ;
2021-11-08 21:25:02 +01:00
import org.pgpainless.algorithm.PublicKeyAlgorithm ;
2021-04-26 13:38:12 +02:00
import org.pgpainless.algorithm.SignatureSubpacket ;
2021-05-06 00:04:03 +02:00
import org.pgpainless.algorithm.SymmetricKeyAlgorithm ;
2021-10-27 17:38:25 +02:00
import org.pgpainless.key.OpenPgpFingerprint ;
2021-04-26 13:38:12 +02:00
import org.pgpainless.key.OpenPgpV4Fingerprint ;
2021-11-08 21:25:02 +01:00
import org.pgpainless.key.generation.type.KeyType ;
2021-05-03 13:37:47 +02:00
import org.pgpainless.signature.SignatureUtils ;
2021-04-26 13:38:12 +02:00
/ * *
* Utility class to access signature subpackets from signatures .
*
* Since rfc4880 is not always clear about where a signature subpacket can be located ( hashed / unhashed area ) ,
* this class makes some educated guesses as to where the subpacket may be found when necessary .
* /
2021-08-15 15:24:19 +02:00
public final class SignatureSubpacketsUtil {
private SignatureSubpacketsUtil ( ) {
}
2021-04-26 13:38:12 +02:00
/ * *
* Return the issuer - fingerprint subpacket of the signature .
* Since this packet is self - authenticating , we expect it to be in the unhashed area ,
* however as it cannot hurt we search for it in the hashed area first .
*
* @param signature signature
* @return issuer fingerprint or null
* /
public static IssuerFingerprint getIssuerFingerprint ( PGPSignature signature ) {
return hashedOrUnhashed ( signature , SignatureSubpacket . issuerFingerprint ) ;
}
2021-05-03 13:37:47 +02:00
/ * *
2021-10-27 17:38:25 +02:00
* Return the { @link IssuerFingerprint } subpacket of the signature into a { @link org . pgpainless . key . OpenPgpFingerprint } .
2021-08-01 16:11:47 +02:00
* If no v4 issuer fingerprint is present in the signature , return null .
2021-05-03 13:37:47 +02:00
*
* @param signature signature
* @return v4 fingerprint of the issuer , or null
* /
2021-10-27 17:38:25 +02:00
public static OpenPgpFingerprint getIssuerFingerprintAsOpenPgpFingerprint ( PGPSignature signature ) {
2021-04-26 13:38:12 +02:00
IssuerFingerprint subpacket = getIssuerFingerprint ( signature ) ;
if ( subpacket = = null ) {
return null ;
}
2021-08-01 16:11:47 +02:00
2021-10-27 17:38:25 +02:00
OpenPgpFingerprint fingerprint = null ;
2021-08-01 16:11:47 +02:00
if ( subpacket . getKeyVersion ( ) = = 4 ) {
2021-10-27 17:38:25 +02:00
fingerprint = new OpenPgpV4Fingerprint ( Hex . encode ( subpacket . getFingerprint ( ) ) ) ;
2021-08-01 16:11:47 +02:00
}
2021-10-27 17:38:25 +02:00
return fingerprint ;
2021-04-26 13:38:12 +02:00
}
/ * *
* Return the issuer key - id subpacket of the signature .
* Since this packet is self - authenticating , we expect it to be in the unhashed area ,
* however as it cannot hurt we search for it in the hashed area first .
*
* @param signature signature
* @return issuer key - id or null
* /
public static IssuerKeyID getIssuerKeyId ( PGPSignature signature ) {
return hashedOrUnhashed ( signature , SignatureSubpacket . issuerKeyId ) ;
}
2021-08-14 11:19:40 +02:00
/ * *
* Inspect the given signature ' s { @link IssuerKeyID } packet to determine the issuer key - id .
* If no such packet is present , return null .
*
* @param signature signature
* @return issuer key - id as { @link Long }
* /
2021-07-22 14:23:21 +02:00
public static Long getIssuerKeyIdAsLong ( PGPSignature signature ) {
IssuerKeyID keyID = getIssuerKeyId ( signature ) ;
if ( keyID = = null ) {
return null ;
}
return keyID . getKeyID ( ) ;
}
2021-04-26 13:38:12 +02:00
/ * *
* Return the revocation reason subpacket of the signature .
* Since this packet is rather important for revocations , we only search for it in the
* hashed area of the signature .
*
* @param signature signature
* @return revocation reason
* /
public static RevocationReason getRevocationReason ( PGPSignature signature ) {
return hashed ( signature , SignatureSubpacket . revocationReason ) ;
}
/ * *
* Return the signature creation time subpacket .
* Since this packet is rather important , we only search for it in the hashed area
* of the signature .
*
* @param signature signature
* @return signature creation time subpacket
* /
public static SignatureCreationTime getSignatureCreationTime ( PGPSignature signature ) {
return hashed ( signature , SignatureSubpacket . signatureCreationTime ) ;
}
/ * *
* Return the signature expiration time subpacket of the signature .
* Since this packet is rather important , we only search for it in the hashed area of the signature .
*
* @param signature signature
* @return signature expiration time
* /
public static SignatureExpirationTime getSignatureExpirationTime ( PGPSignature signature ) {
return hashed ( signature , SignatureSubpacket . signatureExpirationTime ) ;
}
2021-05-03 13:37:47 +02:00
/ * *
2021-12-28 13:53:25 +01:00
* Return the signatures ' expiration time as a date .
2021-05-03 13:37:47 +02:00
* The expiration date is computed by adding the expiration time to the signature creation date .
* If the signature has no expiration time subpacket , or the expiration time is set to '0' , this message returns null .
*
* @param signature signature
* @return expiration time as date
* /
2021-04-26 13:38:12 +02:00
public static Date getSignatureExpirationTimeAsDate ( PGPSignature signature ) {
SignatureExpirationTime subpacket = getSignatureExpirationTime ( signature ) ;
2021-05-03 13:37:47 +02:00
if ( subpacket = = null ) {
2021-04-26 13:38:12 +02:00
return null ;
}
2021-05-03 13:37:47 +02:00
return SignatureUtils . datePlusSeconds ( signature . getCreationTime ( ) , subpacket . getTime ( ) ) ;
2021-04-26 13:38:12 +02:00
}
/ * *
* Return the key expiration time subpacket of this signature .
* We only look for it in the hashed area of the signature .
*
* @param signature signature
* @return key expiration time
* /
public static KeyExpirationTime getKeyExpirationTime ( PGPSignature signature ) {
return hashed ( signature , SignatureSubpacket . keyExpirationTime ) ;
}
2021-05-03 13:37:47 +02:00
/ * *
* Return the signatures key - expiration time as a date .
* The expiration date is computed by adding the signatures ' key - expiration time to the signing keys
* creation date .
* If the signature does not have a key - expiration time subpacket , or its value is '0' , this method returns null .
*
* @param signature self - signature carrying the key - expiration time subpacket
* @param signingKey signature creation key
* @return key expiration time as date
* /
2021-04-26 13:38:12 +02:00
public static Date getKeyExpirationTimeAsDate ( PGPSignature signature , PGPPublicKey signingKey ) {
2021-12-20 12:46:31 +01:00
if ( signature . getKeyID ( ) ! = signingKey . getKeyID ( ) ) {
throw new IllegalArgumentException ( " Provided key ( " + Long . toHexString ( signingKey . getKeyID ( ) ) + " ) did not create the signature ( " + Long . toHexString ( signature . getKeyID ( ) ) + " ) " ) ;
}
2021-04-26 13:38:12 +02:00
KeyExpirationTime subpacket = getKeyExpirationTime ( signature ) ;
2021-05-03 13:37:47 +02:00
if ( subpacket = = null ) {
2021-04-26 13:38:12 +02:00
return null ;
}
2021-12-20 12:46:31 +01:00
2021-05-03 13:37:47 +02:00
return SignatureUtils . datePlusSeconds ( signingKey . getCreationTime ( ) , subpacket . getTime ( ) ) ;
2021-04-26 13:38:12 +02:00
}
2021-11-28 13:09:10 +01:00
/ * *
* Calculate the duration in seconds until the key expires after creation .
*
* @param expirationDate new expiration date
* @param creationDate key creation time
2021-12-28 13:53:25 +01:00
* @return lifetime of the key in seconds
2021-11-28 13:09:10 +01:00
* /
public static long getKeyLifetimeInSeconds ( @Nullable Date expirationDate , @Nonnull Date creationDate ) {
long secondsToExpire = 0 ; // 0 means "no expiration"
if ( expirationDate ! = null ) {
if ( creationDate . after ( expirationDate ) ) {
throw new IllegalArgumentException ( " Key MUST NOT expire before being created. " +
" (creation: " + creationDate + " , expiration: " + expirationDate + " ) " ) ;
}
secondsToExpire = ( expirationDate . getTime ( ) - creationDate . getTime ( ) ) / 1000 ;
}
return secondsToExpire ;
}
2021-04-26 13:38:12 +02:00
/ * *
* Return the revocable subpacket of this signature .
* We only look for it in the hashed area of the signature .
*
* @param signature signature
* @return revocable subpacket
* /
public static Revocable getRevocable ( PGPSignature signature ) {
return hashed ( signature , SignatureSubpacket . revocable ) ;
}
/ * *
* Return the symmetric algorithm preferences from the signatures hashed area .
*
* @param signature signature
* @return symm . algo . prefs
* /
public static PreferredAlgorithms getPreferredSymmetricAlgorithms ( PGPSignature signature ) {
return hashed ( signature , SignatureSubpacket . preferredSymmetricAlgorithms ) ;
}
2021-08-14 11:19:40 +02:00
/ * *
* Return the preferred { @link SymmetricKeyAlgorithm SymmetricKeyAlgorithms } as present in the signature .
* If no preference is given with regard to symmetric encryption algorithms , return an empty set .
*
* In any case , the resulting set is ordered by occurrence ( { @link LinkedHashSet } ) .
* @param signature signature
* @return ordered set of symmetric key algorithm preferences
* /
2021-05-25 13:52:45 +02:00
public static Set < SymmetricKeyAlgorithm > parsePreferredSymmetricKeyAlgorithms ( PGPSignature signature ) {
Set < SymmetricKeyAlgorithm > algorithms = new LinkedHashSet < > ( ) ;
2021-05-06 00:04:03 +02:00
PreferredAlgorithms preferences = getPreferredSymmetricAlgorithms ( signature ) ;
if ( preferences ! = null ) {
for ( int code : preferences . getPreferences ( ) ) {
algorithms . add ( SymmetricKeyAlgorithm . fromId ( code ) ) ;
}
}
return algorithms ;
}
2021-04-26 13:38:12 +02:00
/ * *
* Return the hash algorithm preferences from the signatures hashed area .
*
* @param signature signature
* @return hash algo prefs
* /
public static PreferredAlgorithms getPreferredHashAlgorithms ( PGPSignature signature ) {
return hashed ( signature , SignatureSubpacket . preferredHashAlgorithms ) ;
}
2021-08-14 11:19:40 +02:00
/ * *
* Return the preferred { @link HashAlgorithm HashAlgorithms } as present in the signature .
* If no preference is given with regard to hash algorithms , return an empty set .
*
* In any case , the resulting set is ordered by occurrence ( { @link LinkedHashSet } ) .
* @param signature signature
* @return ordered set of hash algorithm preferences
* /
2021-05-25 13:52:45 +02:00
public static Set < HashAlgorithm > parsePreferredHashAlgorithms ( PGPSignature signature ) {
Set < HashAlgorithm > algorithms = new LinkedHashSet < > ( ) ;
2021-05-06 00:04:03 +02:00
PreferredAlgorithms preferences = getPreferredHashAlgorithms ( signature ) ;
if ( preferences ! = null ) {
for ( int code : preferences . getPreferences ( ) ) {
algorithms . add ( HashAlgorithm . fromId ( code ) ) ;
}
}
return algorithms ;
}
2021-04-26 13:38:12 +02:00
/ * *
* Return the compression algorithm preferences from the signatures hashed area .
*
* @param signature signature
* @return compression algo prefs
* /
public static PreferredAlgorithms getPreferredCompressionAlgorithms ( PGPSignature signature ) {
return hashed ( signature , SignatureSubpacket . preferredCompressionAlgorithms ) ;
}
2021-08-14 11:19:40 +02:00
/ * *
* Return the preferred { @link CompressionAlgorithm CompressionAlgorithms } as present in the signature .
* If no preference is given with regard to compression algorithms , return an empty set .
*
* In any case , the resulting set is ordered by occurrence ( { @link LinkedHashSet } ) .
* @param signature signature
* @return ordered set of compression algorithm preferences
* /
2021-05-25 13:52:45 +02:00
public static Set < CompressionAlgorithm > parsePreferredCompressionAlgorithms ( PGPSignature signature ) {
Set < CompressionAlgorithm > algorithms = new LinkedHashSet < > ( ) ;
2021-05-06 00:04:03 +02:00
PreferredAlgorithms preferences = getPreferredCompressionAlgorithms ( signature ) ;
if ( preferences ! = null ) {
for ( int code : preferences . getPreferences ( ) ) {
algorithms . add ( CompressionAlgorithm . fromId ( code ) ) ;
}
}
return algorithms ;
}
2021-04-26 13:38:12 +02:00
/ * *
* Return the primary user - id subpacket from the signatures hashed area .
*
* @param signature signature
* @return primary user id
* /
public static PrimaryUserID getPrimaryUserId ( PGPSignature signature ) {
return hashed ( signature , SignatureSubpacket . primaryUserId ) ;
}
/ * *
* Return the key flags subpacket from the signatures hashed area .
*
* @param signature signature
* @return key flags
* /
public static KeyFlags getKeyFlags ( PGPSignature signature ) {
return hashed ( signature , SignatureSubpacket . keyFlags ) ;
}
2021-05-06 00:04:03 +02:00
/ * *
* Return a list of key flags carried by the signature .
* If the signature is null , or has no { @link KeyFlags } subpacket , return null .
*
* @param signature signature
* @return list of key flags
* /
public static List < KeyFlag > parseKeyFlags ( @Nullable PGPSignature signature ) {
if ( signature = = null ) {
return null ;
}
KeyFlags keyFlags = getKeyFlags ( signature ) ;
if ( keyFlags = = null ) {
return null ;
}
return KeyFlag . fromBitmask ( keyFlags . getFlags ( ) ) ;
}
2021-04-26 13:38:12 +02:00
/ * *
* Return the features subpacket from the signatures hashed area .
*
* @param signature signature
* @return features subpacket
* /
public static Features getFeatures ( PGPSignature signature ) {
return hashed ( signature , SignatureSubpacket . features ) ;
}
2021-10-04 13:32:04 +02:00
/ * *
* Parse out the features subpacket of a signature .
* If the signature has no features subpacket , return null .
* Otherwise , return the features as a feature set .
*
* @param signature signature
* @return features as set
* /
public static @Nullable Set < Feature > parseFeatures ( PGPSignature signature ) {
Features features = getFeatures ( signature ) ;
if ( features = = null ) {
return null ;
}
return new LinkedHashSet < > ( Feature . fromBitmask ( features . getData ( ) [ 0 ] ) ) ;
}
2021-04-26 13:38:12 +02:00
/ * *
* Return the signature target subpacket from the signature .
* We search for this subpacket in the hashed and unhashed area ( in this order ) .
*
* @param signature signature
* @return signature target
* /
public static SignatureTarget getSignatureTarget ( PGPSignature signature ) {
return hashedOrUnhashed ( signature , SignatureSubpacket . signatureTarget ) ;
}
/ * *
* Return the notation data subpackets from the signatures hashed area .
*
* @param signature signature
* @return hashed notations
* /
public static List < NotationData > getHashedNotationData ( PGPSignature signature ) {
NotationData [ ] notations = signature . getHashedSubPackets ( ) . getNotationDataOccurrences ( ) ;
return Arrays . asList ( notations ) ;
}
2021-08-14 11:19:40 +02:00
/ * *
* Return a list of all { @link NotationData } objects from the hashed area of the signature that have a
* notation name equal to the given notationName argument .
*
* @param signature signature
* @param notationName notation name
* @return list of matching notation data objects
* /
2021-06-10 13:35:55 +02:00
public static List < NotationData > getHashedNotationData ( PGPSignature signature , String notationName ) {
List < NotationData > allNotations = getHashedNotationData ( signature ) ;
List < NotationData > withName = new ArrayList < > ( ) ;
for ( NotationData data : allNotations ) {
if ( data . getNotationName ( ) . equals ( notationName ) ) {
withName . add ( data ) ;
}
}
return withName ;
}
2021-04-26 13:38:12 +02:00
/ * *
* Return the notation data subpackets from the signatures unhashed area .
*
* @param signature signture
* @return unhashed notations
* /
public static List < NotationData > getUnhashedNotationData ( PGPSignature signature ) {
NotationData [ ] notations = signature . getUnhashedSubPackets ( ) . getNotationDataOccurrences ( ) ;
return Arrays . asList ( notations ) ;
}
2021-08-14 11:19:40 +02:00
/ * *
* Return a list of all { @link NotationData } objects from the unhashed area of the signature that have a
* notation name equal to the given notationName argument .
*
* @param signature signature
* @param notationName notation name
* @return list of matching notation data objects
* /
2021-06-10 13:35:55 +02:00
public static List < NotationData > getUnhashedNotationData ( PGPSignature signature , String notationName ) {
List < NotationData > allNotations = getUnhashedNotationData ( signature ) ;
List < NotationData > withName = new ArrayList < > ( ) ;
for ( NotationData data : allNotations ) {
if ( data . getNotationName ( ) . equals ( notationName ) ) {
withName . add ( data ) ;
}
}
return withName ;
}
2021-04-26 13:38:12 +02:00
/ * *
* Return the revocation key subpacket from the signatures hashed area .
*
* @param signature signature
* @return revocation key
* /
public static RevocationKey getRevocationKey ( PGPSignature signature ) {
return hashed ( signature , SignatureSubpacket . revocationKey ) ;
}
/ * *
* Return the signers user - id from the hashed area of the signature .
* TODO : Can this subpacket also be found in the unhashed area ?
*
* @param signature signature
* @return signers user - id
* /
public static SignerUserID getSignerUserID ( PGPSignature signature ) {
return hashed ( signature , SignatureSubpacket . signerUserId ) ;
}
/ * *
* Return the intended recipients fingerprint subpackets from the hashed area of this signature .
*
* @param signature signature
* @return intended recipient fingerprint subpackets
* /
public static List < IntendedRecipientFingerprint > getIntendedRecipientFingerprints ( PGPSignature signature ) {
org . bouncycastle . bcpg . SignatureSubpacket [ ] subpackets = signature . getHashedSubPackets ( ) . getSubpackets ( SignatureSubpacket . intendedRecipientFingerprint . getCode ( ) ) ;
List < IntendedRecipientFingerprint > intendedRecipients = new ArrayList < > ( subpackets . length ) ;
for ( org . bouncycastle . bcpg . SignatureSubpacket subpacket : subpackets ) {
intendedRecipients . add ( ( IntendedRecipientFingerprint ) subpacket ) ;
}
return intendedRecipients ;
}
/ * *
* Return the embedded signature subpacket from the signatures hashed area .
*
* @param signature signature
* @return embedded signature
* /
public static PGPSignatureList getEmbeddedSignature ( PGPSignature signature ) throws PGPException {
PGPSignatureList hashed = signature . getHashedSubPackets ( ) . getEmbeddedSignatures ( ) ;
if ( ! hashed . isEmpty ( ) ) {
return hashed ;
}
return signature . getUnhashedSubPackets ( ) . getEmbeddedSignatures ( ) ;
}
/ * *
* Return the signatures exportable certification subpacket from the hashed area .
*
* @param signature signature
* @return exportable certification subpacket
* /
public static Exportable getExportableCertification ( PGPSignature signature ) {
return hashed ( signature , SignatureSubpacket . exportableCertification ) ;
}
/ * *
* Return the trust signature packet from the signatures hashed area .
*
* @param signature signature
* @return trust signature subpacket
* /
public static TrustSignature getTrustSignature ( PGPSignature signature ) {
return hashed ( signature , SignatureSubpacket . trustSignature ) ;
}
2021-05-03 13:37:47 +02:00
/ * *
* Select a list of all signature subpackets of the given type , which are present in the hashed area of
* the given signature .
*
* @param signature signature
* @param type subpacket type
* @param < P > generic subpacket type
* @return list of subpackets from the hashed area
* /
2021-04-26 13:38:12 +02:00
private static < P extends org . bouncycastle . bcpg . SignatureSubpacket > P hashed ( PGPSignature signature , SignatureSubpacket type ) {
return getSignatureSubpacket ( signature . getHashedSubPackets ( ) , type ) ;
}
2021-05-03 13:37:47 +02:00
/ * *
* Select a list of all signature subpackets of the given type , which are present in the unhashed area of
* the given signature .
*
* @param signature signature
* @param type subpacket type
* @param < P > generic subpacket type
* @return list of subpackets from the unhashed area
* /
2021-04-26 13:38:12 +02:00
private static < P extends org . bouncycastle . bcpg . SignatureSubpacket > P unhashed ( PGPSignature signature , SignatureSubpacket type ) {
return getSignatureSubpacket ( signature . getUnhashedSubPackets ( ) , type ) ;
}
2021-05-03 13:37:47 +02:00
/ * *
* Select a list of all signature subpackets of the given type , which are present in either the hashed
* or the unhashed area of the given signature .
*
* @param signature signature
* @param type subpacket type
* @param < P > generic subpacket type
* @return list of subpackets from the hashed / unhashed area
* /
2021-04-26 13:38:12 +02:00
private static < P extends org . bouncycastle . bcpg . SignatureSubpacket > P hashedOrUnhashed ( PGPSignature signature , SignatureSubpacket type ) {
P hashedSubpacket = hashed ( signature , type ) ;
return hashedSubpacket ! = null ? hashedSubpacket : unhashed ( signature , type ) ;
}
/ * *
* Return the last occurence of a subpacket type in the given signature subpacket vector .
*
* @param vector subpacket vector ( hashed / unhashed )
* @param type subpacket type
* @param < P > generic return type of the subpacket
* @return last occurrence of the subpacket in the vector
* /
public static < P extends org . bouncycastle . bcpg . SignatureSubpacket > P getSignatureSubpacket ( PGPSignatureSubpacketVector vector , SignatureSubpacket type ) {
org . bouncycastle . bcpg . SignatureSubpacket [ ] allPackets = vector . getSubpackets ( type . getCode ( ) ) ;
if ( allPackets . length = = 0 ) {
return null ;
}
return ( P ) allPackets [ allPackets . length - 1 ] ; // return last
}
2021-11-08 21:25:02 +01:00
/ * *
* Make sure that the given key type can carry the given key flags .
*
* @param type key type
* @param flags key flags
* /
public static void assureKeyCanCarryFlags ( KeyType type , KeyFlag . . . flags ) {
final int mask = KeyFlag . toBitmask ( flags ) ;
if ( ! type . canCertify ( ) & & KeyFlag . hasKeyFlag ( mask , KeyFlag . CERTIFY_OTHER ) ) {
throw new IllegalArgumentException ( " KeyType " + type . getName ( ) + " cannot carry key flag CERTIFY_OTHER. " ) ;
}
if ( ! type . canSign ( ) & & KeyFlag . hasKeyFlag ( mask , KeyFlag . SIGN_DATA ) ) {
throw new IllegalArgumentException ( " KeyType " + type . getName ( ) + " cannot carry key flag SIGN_DATA. " ) ;
}
if ( ! type . canEncryptCommunication ( ) & & KeyFlag . hasKeyFlag ( mask , KeyFlag . ENCRYPT_COMMS ) ) {
throw new IllegalArgumentException ( " KeyType " + type . getName ( ) + " cannot carry key flag ENCRYPT_COMMS. " ) ;
}
if ( ! type . canEncryptStorage ( ) & & KeyFlag . hasKeyFlag ( mask , KeyFlag . ENCRYPT_STORAGE ) ) {
throw new IllegalArgumentException ( " KeyType " + type . getName ( ) + " cannot carry key flag ENCRYPT_STORAGE. " ) ;
}
if ( ! type . canAuthenticate ( ) & & KeyFlag . hasKeyFlag ( mask , KeyFlag . AUTHENTICATION ) ) {
2021-11-28 13:22:08 +01:00
throw new IllegalArgumentException ( " KeyType " + type . getName ( ) + " cannot carry key flag AUTHENTICATION. " ) ;
2021-11-08 21:25:02 +01:00
}
}
public static void assureKeyCanCarryFlags ( PublicKeyAlgorithm algorithm , KeyFlag . . . flags ) {
final int mask = KeyFlag . toBitmask ( flags ) ;
if ( ! algorithm . isSigningCapable ( ) & & KeyFlag . hasKeyFlag ( mask , KeyFlag . CERTIFY_OTHER ) ) {
throw new IllegalArgumentException ( " Algorithm " + algorithm + " cannot be used with key flag CERTIFY_OTHER. " ) ;
}
if ( ! algorithm . isSigningCapable ( ) & & KeyFlag . hasKeyFlag ( mask , KeyFlag . SIGN_DATA ) ) {
throw new IllegalArgumentException ( " Algorithm " + algorithm + " cannot be used with key flag SIGN_DATA. " ) ;
}
if ( ! algorithm . isEncryptionCapable ( ) & & KeyFlag . hasKeyFlag ( mask , KeyFlag . ENCRYPT_COMMS ) ) {
throw new IllegalArgumentException ( " Algorithm " + algorithm + " cannot be used with key flag ENCRYPT_COMMS. " ) ;
}
if ( ! algorithm . isEncryptionCapable ( ) & & KeyFlag . hasKeyFlag ( mask , KeyFlag . ENCRYPT_STORAGE ) ) {
throw new IllegalArgumentException ( " Algorithm " + algorithm + " cannot be used with key flag ENCRYPT_STORAGE. " ) ;
}
if ( ! algorithm . isSigningCapable ( ) & & KeyFlag . hasKeyFlag ( mask , KeyFlag . AUTHENTICATION ) ) {
2021-11-28 13:22:08 +01:00
throw new IllegalArgumentException ( " Algorithm " + algorithm + " cannot be used with key flag AUTHENTICATION. " ) ;
2021-11-08 21:25:02 +01:00
}
}
2021-04-26 13:38:12 +02:00
}