1
0
Fork 0
mirror of https://github.com/pgpainless/pgpainless.git synced 2024-11-26 06:12:06 +01:00

Annotate fromId(code) methods with Nullable and add Nonnull requireFromId(code) methods

This commit is contained in:
Paul Schaub 2022-03-22 15:09:09 +01:00
parent 16b0d0730e
commit e8b03834cb
Signed by: vanitasvitae
GPG key ID: 62BEE9264BF17311
24 changed files with 278 additions and 42 deletions

View file

@ -5,10 +5,14 @@
package org.pgpainless.algorithm; package org.pgpainless.algorithm;
import java.util.Map; import java.util.Map;
import java.util.NoSuchElementException;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import org.bouncycastle.bcpg.CompressionAlgorithmTags; import org.bouncycastle.bcpg.CompressionAlgorithmTags;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/** /**
* Enumeration of possible compression algorithms. * Enumeration of possible compression algorithms.
* *
@ -37,10 +41,28 @@ public enum CompressionAlgorithm {
* @param id id * @param id id
* @return compression algorithm * @return compression algorithm
*/ */
@Nullable
public static CompressionAlgorithm fromId(int id) { public static CompressionAlgorithm fromId(int id) {
return MAP.get(id); return MAP.get(id);
} }
/**
* Return the {@link CompressionAlgorithm} value that corresponds to the provided numerical id.
* If an invalid id is provided, thrown an {@link NoSuchElementException}.
*
* @param id id
* @return compression algorithm
* @throws NoSuchElementException in case of an unmapped id
*/
@Nonnull
public static CompressionAlgorithm requireFromId(int id) {
CompressionAlgorithm algorithm = fromId(id);
if (algorithm == null) {
throw new NoSuchElementException("No CompressionAlgorithm found for id " + id);
}
return algorithm;
}
private final int algorithmId; private final int algorithmId;
CompressionAlgorithm(int id) { CompressionAlgorithm(int id) {

View file

@ -7,10 +7,14 @@ package org.pgpainless.algorithm;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.NoSuchElementException;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import org.bouncycastle.bcpg.sig.Features; import org.bouncycastle.bcpg.sig.Features;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/** /**
* An enumeration of features that may be set in the {@link Features} subpacket. * An enumeration of features that may be set in the {@link Features} subpacket.
* *
@ -60,16 +64,46 @@ public enum Feature {
} }
} }
/**
* Return the {@link Feature} encoded by the given id.
* If the id does not match any known features, return null.
*
* @param id feature id
* @return feature
*/
@Nullable
public static Feature fromId(byte id) { public static Feature fromId(byte id) {
return MAP.get(id); return MAP.get(id);
} }
/**
* Return the {@link Feature} encoded by the given id.
* If the id does not match any known features, throw an {@link NoSuchElementException}.
*
* @param id feature id
* @return feature
* @throws NoSuchElementException if an unmatched feature id is encountered
*/
@Nonnull
public static Feature requireFromId(byte id) {
Feature feature = fromId(id);
if (feature == null) {
throw new NoSuchElementException("Unknown feature id encountered: " + id);
}
return feature;
}
private final byte featureId; private final byte featureId;
Feature(byte featureId) { Feature(byte featureId) {
this.featureId = featureId; this.featureId = featureId;
} }
/**
* Return the id of the feature.
*
* @return feature id
*/
public byte getFeatureId() { public byte getFeatureId() {
return featureId; return featureId;
} }
@ -80,6 +114,7 @@ public enum Feature {
* @param bitmask bitmask * @param bitmask bitmask
* @return list of key flags encoded by the bitmask * @return list of key flags encoded by the bitmask
*/ */
@Nonnull
public static List<Feature> fromBitmask(int bitmask) { public static List<Feature> fromBitmask(int bitmask) {
List<Feature> features = new ArrayList<>(); List<Feature> features = new ArrayList<>();
for (Feature f : Feature.values()) { for (Feature f : Feature.values()) {

View file

@ -6,9 +6,13 @@ package org.pgpainless.algorithm;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.NoSuchElementException;
import org.bouncycastle.bcpg.HashAlgorithmTags; import org.bouncycastle.bcpg.HashAlgorithmTags;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/** /**
* An enumeration of different hashing algorithms. * An enumeration of different hashing algorithms.
* *
@ -42,10 +46,28 @@ public enum HashAlgorithm {
* @param id numeric id * @param id numeric id
* @return enum value * @return enum value
*/ */
@Nullable
public static HashAlgorithm fromId(int id) { public static HashAlgorithm fromId(int id) {
return ID_MAP.get(id); return ID_MAP.get(id);
} }
/**
* Return the {@link HashAlgorithm} value that corresponds to the provided algorithm id.
* If an invalid algorithm id was provided, throw a {@link NoSuchElementException}.
*
* @param id algorithm id
* @return enum value
* @throws NoSuchElementException in case of an unknown algorithm id
*/
@Nonnull
public static HashAlgorithm requireFromId(int id) {
HashAlgorithm algorithm = fromId(id);
if (algorithm == null) {
throw new NoSuchElementException("No HashAlgorithm found for id " + id);
}
return algorithm;
}
/** /**
* Return the {@link HashAlgorithm} value that corresponds to the provided name. * Return the {@link HashAlgorithm} value that corresponds to the provided name.
* If an invalid algorithm name was provided, null is returned. * If an invalid algorithm name was provided, null is returned.
@ -56,6 +78,7 @@ public enum HashAlgorithm {
* @param name text name * @param name text name
* @return enum value * @return enum value
*/ */
@Nullable
public static HashAlgorithm fromName(String name) { public static HashAlgorithm fromName(String name) {
return NAME_MAP.get(name); return NAME_MAP.get(name);
} }

View file

@ -5,10 +5,14 @@
package org.pgpainless.algorithm; package org.pgpainless.algorithm;
import java.util.Map; import java.util.Map;
import java.util.NoSuchElementException;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import org.bouncycastle.bcpg.PublicKeyAlgorithmTags; import org.bouncycastle.bcpg.PublicKeyAlgorithmTags;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/** /**
* Enumeration of public key algorithms as defined in RFC4880. * Enumeration of public key algorithms as defined in RFC4880.
* *
@ -96,12 +100,30 @@ public enum PublicKeyAlgorithm {
* If an invalid id is provided, null is returned. * If an invalid id is provided, null is returned.
* *
* @param id numeric algorithm id * @param id numeric algorithm id
* @return algorithm * @return algorithm or null
*/ */
@Nullable
public static PublicKeyAlgorithm fromId(int id) { public static PublicKeyAlgorithm fromId(int id) {
return MAP.get(id); return MAP.get(id);
} }
/**
* Return the {@link PublicKeyAlgorithm} that corresponds to the provided algorithm id.
* If an invalid id is provided, throw a {@link NoSuchElementException}.
*
* @param id numeric algorithm id
* @return algorithm
* @throws NoSuchElementException in case of an unmatched algorithm id
*/
@Nonnull
public static PublicKeyAlgorithm requireFromId(int id) {
PublicKeyAlgorithm algorithm = fromId(id);
if (algorithm == null) {
throw new NoSuchElementException("No PublicKeyAlgorithm found for id " + id);
}
return algorithm;
}
private final int algorithmId; private final int algorithmId;
private final boolean signingCapable; private final boolean signingCapable;
private final boolean encryptionCapable; private final boolean encryptionCapable;

View file

@ -4,6 +4,9 @@
package org.pgpainless.algorithm; package org.pgpainless.algorithm;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import static org.bouncycastle.bcpg.SignatureSubpacketTags.ATTESTED_CERTIFICATIONS; import static org.bouncycastle.bcpg.SignatureSubpacketTags.ATTESTED_CERTIFICATIONS;
import static org.bouncycastle.bcpg.SignatureSubpacketTags.CREATION_TIME; import static org.bouncycastle.bcpg.SignatureSubpacketTags.CREATION_TIME;
import static org.bouncycastle.bcpg.SignatureSubpacketTags.EMBEDDED_SIGNATURE; import static org.bouncycastle.bcpg.SignatureSubpacketTags.EMBEDDED_SIGNATURE;
@ -36,6 +39,7 @@ import static org.bouncycastle.bcpg.SignatureSubpacketTags.TRUST_SIG;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.NoSuchElementException;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
/** /**
@ -412,14 +416,28 @@ public enum SignatureSubpacket {
/** /**
* Return the {@link SignatureSubpacket} that corresponds to the provided id. * Return the {@link SignatureSubpacket} that corresponds to the provided id.
* If an unmatched code is presented, return null.
* *
* @param code id * @param code id
* @return signature subpacket * @return signature subpacket
*/ */
@Nullable
public static SignatureSubpacket fromCode(int code) { public static SignatureSubpacket fromCode(int code) {
SignatureSubpacket tag = MAP.get(code); return MAP.get(code);
}
/**
* Return the {@link SignatureSubpacket} that corresponds to the provided code.
*
* @param code code
* @return signature subpacket
* @throws NoSuchElementException in case of an unmatched subpacket tag
*/
@Nonnull
public static SignatureSubpacket requireFromCode(int code) {
SignatureSubpacket tag = fromCode(code);
if (tag == null) { if (tag == null) {
throw new IllegalArgumentException("No SignatureSubpacket tag found with code " + code); throw new NoSuchElementException("No SignatureSubpacket tag found with code " + code);
} }
return tag; return tag;
} }
@ -433,7 +451,11 @@ public enum SignatureSubpacket {
public static List<SignatureSubpacket> fromCodes(int[] codes) { public static List<SignatureSubpacket> fromCodes(int[] codes) {
List<SignatureSubpacket> tags = new ArrayList<>(); List<SignatureSubpacket> tags = new ArrayList<>();
for (int code : codes) { for (int code : codes) {
tags.add(fromCode(code)); try {
tags.add(requireFromCode(code));
} catch (NoSuchElementException e) {
// skip
}
} }
return tags; return tags;
} }

View file

@ -6,6 +6,7 @@ package org.pgpainless.algorithm;
import org.bouncycastle.openpgp.PGPSignature; import org.bouncycastle.openpgp.PGPSignature;
import javax.annotation.Nonnull;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@ -167,7 +168,9 @@ public enum SignatureType {
* *
* @param code numeric id * @param code numeric id
* @return signature type enum * @return signature type enum
* @throws IllegalArgumentException in case of an unmatched signature type code
*/ */
@Nonnull
public static SignatureType valueOf(int code) { public static SignatureType valueOf(int code) {
SignatureType type = map.get(code); SignatureType type = map.get(code);
if (type != null) { if (type != null) {

View file

@ -5,10 +5,14 @@
package org.pgpainless.algorithm; package org.pgpainless.algorithm;
import java.util.Map; import java.util.Map;
import java.util.NoSuchElementException;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import org.bouncycastle.openpgp.PGPLiteralData; import org.bouncycastle.openpgp.PGPLiteralData;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/** /**
* Enumeration of possible encoding formats of the content of the literal data packet. * Enumeration of possible encoding formats of the content of the literal data packet.
* *
@ -78,11 +82,31 @@ public enum StreamEncoding {
/** /**
* Return the {@link StreamEncoding} corresponding to the provided code identifier. * Return the {@link StreamEncoding} corresponding to the provided code identifier.
* If no matching encoding is found, return null.
* *
* @param code identifier * @param code identifier
* @return encoding enum * @return encoding enum
*/ */
@Nullable
public static StreamEncoding fromCode(int code) { public static StreamEncoding fromCode(int code) {
return MAP.get((char) code); return MAP.get((char) code);
} }
/**
* Return the {@link StreamEncoding} corresponding to the provided code identifier.
* If no matching encoding is found, throw a {@link NoSuchElementException}.
*
* @param code identifier
* @return encoding enum
*
* @throws NoSuchElementException in case of an unmatched identifier
*/
@Nonnull
public static StreamEncoding requireFromCode(int code) {
StreamEncoding encoding = fromCode(code);
if (encoding == null) {
throw new NoSuchElementException("No StreamEncoding found for code " + code);
}
return encoding;
}
} }

View file

@ -5,10 +5,14 @@
package org.pgpainless.algorithm; package org.pgpainless.algorithm;
import java.util.Map; import java.util.Map;
import java.util.NoSuchElementException;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags; import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/** /**
* Enumeration of possible symmetric encryption algorithms. * Enumeration of possible symmetric encryption algorithms.
* *
@ -106,10 +110,29 @@ public enum SymmetricKeyAlgorithm {
* @param id numeric algorithm id * @param id numeric algorithm id
* @return symmetric key algorithm enum * @return symmetric key algorithm enum
*/ */
@Nullable
public static SymmetricKeyAlgorithm fromId(int id) { public static SymmetricKeyAlgorithm fromId(int id) {
return MAP.get(id); return MAP.get(id);
} }
/**
* Return the {@link SymmetricKeyAlgorithm} enum that corresponds to the provided numeric id.
* If an invalid id is provided, throw a {@link NoSuchElementException}.
*
* @param id numeric algorithm id
* @return symmetric key algorithm enum
*
* @throws NoSuchElementException if an unmatched id is provided
*/
@Nonnull
public static SymmetricKeyAlgorithm requireFromId(int id) {
SymmetricKeyAlgorithm algorithm = fromId(id);
if (algorithm == null) {
throw new NoSuchElementException("No SymmetricKeyAlgorithm found for id " + id);
}
return algorithm;
}
private final int algorithmId; private final int algorithmId;
SymmetricKeyAlgorithm(int algorithmId) { SymmetricKeyAlgorithm(int algorithmId) {

View file

@ -14,6 +14,7 @@ import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set; import java.util.Set;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -310,9 +311,13 @@ public final class DecryptionStreamFactory {
private InputStream processPGPCompressedData(PGPCompressedData pgpCompressedData, int depth) private InputStream processPGPCompressedData(PGPCompressedData pgpCompressedData, int depth)
throws PGPException, IOException { throws PGPException, IOException {
CompressionAlgorithm compressionAlgorithm = CompressionAlgorithm.fromId(pgpCompressedData.getAlgorithm()); try {
CompressionAlgorithm compressionAlgorithm = CompressionAlgorithm.requireFromId(pgpCompressedData.getAlgorithm());
LOGGER.debug("Depth {}: Encountered PGPCompressedData: {}", depth, compressionAlgorithm); LOGGER.debug("Depth {}: Encountered PGPCompressedData: {}", depth, compressionAlgorithm);
resultBuilder.setCompressionAlgorithm(compressionAlgorithm); resultBuilder.setCompressionAlgorithm(compressionAlgorithm);
} catch (NoSuchElementException e) {
throw new PGPException("Unknown compression algorithm encountered.", e);
}
InputStream inflatedDataStream = pgpCompressedData.getDataStream(); InputStream inflatedDataStream = pgpCompressedData.getDataStream();
InputStream decodedDataStream = PGPUtil.getDecoderStream(inflatedDataStream); InputStream decodedDataStream = PGPUtil.getDecoderStream(inflatedDataStream);
@ -340,7 +345,7 @@ public final class DecryptionStreamFactory {
resultBuilder.setFileName(pgpLiteralData.getFileName()) resultBuilder.setFileName(pgpLiteralData.getFileName())
.setModificationDate(pgpLiteralData.getModificationTime()) .setModificationDate(pgpLiteralData.getModificationTime())
.setFileEncoding(StreamEncoding.fromCode(pgpLiteralData.getFormat())); .setFileEncoding(StreamEncoding.requireFromCode(pgpLiteralData.getFormat()));
if (onePassSignatureChecks.isEmpty() && onePassSignaturesWithMissingCert.isEmpty()) { if (onePassSignatureChecks.isEmpty() && onePassSignaturesWithMissingCert.isEmpty()) {
LOGGER.debug("No OnePassSignatures found -> We are done"); LOGGER.debug("No OnePassSignatures found -> We are done");

View file

@ -320,7 +320,7 @@ public final class SigningOptions {
throws PGPException { throws PGPException {
SubkeyIdentifier signingKeyIdentifier = new SubkeyIdentifier(secretKey, signingSubkey.getKeyID()); SubkeyIdentifier signingKeyIdentifier = new SubkeyIdentifier(secretKey, signingSubkey.getKeyID());
PGPSecretKey signingSecretKey = secretKey.getSecretKey(signingSubkey.getKeyID()); PGPSecretKey signingSecretKey = secretKey.getSecretKey(signingSubkey.getKeyID());
PublicKeyAlgorithm publicKeyAlgorithm = PublicKeyAlgorithm.fromId(signingSecretKey.getPublicKey().getAlgorithm()); PublicKeyAlgorithm publicKeyAlgorithm = PublicKeyAlgorithm.requireFromId(signingSecretKey.getPublicKey().getAlgorithm());
int bitStrength = secretKey.getPublicKey().getBitStrength(); int bitStrength = secretKey.getPublicKey().getBitStrength();
if (!PGPainless.getPolicy().getPublicKeyAlgorithmPolicy().isAcceptable(publicKeyAlgorithm, bitStrength)) { if (!PGPainless.getPolicy().getPublicKeyAlgorithmPolicy().isAcceptable(publicKeyAlgorithm, bitStrength)) {
throw new IllegalArgumentException("Public key algorithm policy violation: " + throw new IllegalArgumentException("Public key algorithm policy violation: " +

View file

@ -58,7 +58,7 @@ public class BcImplementationFactory extends ImplementationFactory {
int keyEncryptionAlgorithm = secretKey.getKeyEncryptionAlgorithm(); int keyEncryptionAlgorithm = secretKey.getKeyEncryptionAlgorithm();
if (secretKey.getS2K() == null) { if (secretKey.getS2K() == null) {
return getPBESecretKeyEncryptor(SymmetricKeyAlgorithm.fromId(keyEncryptionAlgorithm), passphrase); return getPBESecretKeyEncryptor(SymmetricKeyAlgorithm.requireFromId(keyEncryptionAlgorithm), passphrase);
} }
int hashAlgorithm = secretKey.getS2K().getHashAlgorithm(); int hashAlgorithm = secretKey.getS2K().getHashAlgorithm();

View file

@ -65,7 +65,7 @@ public class KeyInfo {
} }
public static String getCurveName(PGPPublicKey publicKey) { public static String getCurveName(PGPPublicKey publicKey) {
PublicKeyAlgorithm algorithm = PublicKeyAlgorithm.fromId(publicKey.getAlgorithm()); PublicKeyAlgorithm algorithm = PublicKeyAlgorithm.requireFromId(publicKey.getAlgorithm());
ECPublicBCPGKey key; ECPublicBCPGKey key;
switch (algorithm) { switch (algorithm) {
case ECDSA: { case ECDSA: {

View file

@ -567,8 +567,9 @@ public class KeyRingInfo {
* *
* @return public key algorithm * @return public key algorithm
*/ */
@Nonnull
public PublicKeyAlgorithm getAlgorithm() { public PublicKeyAlgorithm getAlgorithm() {
return PublicKeyAlgorithm.fromId(getPublicKey().getAlgorithm()); return PublicKeyAlgorithm.requireFromId(getPublicKey().getAlgorithm());
} }
/** /**

View file

@ -272,11 +272,11 @@ public class SecretKeyRingEditor implements SecretKeyRingEditorInterface {
KeyFlag... additionalKeyFlags) KeyFlag... additionalKeyFlags)
throws PGPException, IOException, NoSuchAlgorithmException { throws PGPException, IOException, NoSuchAlgorithmException {
KeyFlag[] flags = concat(keyFlag, additionalKeyFlags); KeyFlag[] flags = concat(keyFlag, additionalKeyFlags);
PublicKeyAlgorithm subkeyAlgorithm = PublicKeyAlgorithm.fromId(subkey.getPublicKey().getAlgorithm()); PublicKeyAlgorithm subkeyAlgorithm = PublicKeyAlgorithm.requireFromId(subkey.getPublicKey().getAlgorithm());
SignatureSubpacketsUtil.assureKeyCanCarryFlags(subkeyAlgorithm); SignatureSubpacketsUtil.assureKeyCanCarryFlags(subkeyAlgorithm);
// check key against public key algorithm policy // check key against public key algorithm policy
PublicKeyAlgorithm publicKeyAlgorithm = PublicKeyAlgorithm.fromId(subkey.getPublicKey().getAlgorithm()); PublicKeyAlgorithm publicKeyAlgorithm = PublicKeyAlgorithm.requireFromId(subkey.getPublicKey().getAlgorithm());
int bitStrength = subkey.getPublicKey().getBitStrength(); int bitStrength = subkey.getPublicKey().getBitStrength();
if (!PGPainless.getPolicy().getPublicKeyAlgorithmPolicy().isAcceptable(publicKeyAlgorithm, bitStrength)) { if (!PGPainless.getPolicy().getPublicKeyAlgorithmPolicy().isAcceptable(publicKeyAlgorithm, bitStrength)) {
throw new IllegalArgumentException("Public key algorithm policy violation: " + throw new IllegalArgumentException("Public key algorithm policy violation: " +
@ -285,7 +285,7 @@ public class SecretKeyRingEditor implements SecretKeyRingEditorInterface {
PGPSecretKey primaryKey = secretKeyRing.getSecretKey(); PGPSecretKey primaryKey = secretKeyRing.getSecretKey();
KeyRingInfo info = PGPainless.inspectKeyRing(secretKeyRing); KeyRingInfo info = PGPainless.inspectKeyRing(secretKeyRing);
PublicKeyAlgorithm signingKeyAlgorithm = PublicKeyAlgorithm.fromId(primaryKey.getPublicKey().getAlgorithm()); PublicKeyAlgorithm signingKeyAlgorithm = PublicKeyAlgorithm.requireFromId(primaryKey.getPublicKey().getAlgorithm());
HashAlgorithm hashAlgorithm = HashAlgorithmNegotiator HashAlgorithm hashAlgorithm = HashAlgorithmNegotiator
.negotiateSignatureHashAlgorithm(PGPainless.getPolicy()) .negotiateSignatureHashAlgorithm(PGPainless.getPolicy())
.negotiateHashAlgorithm(info.getPreferredHashAlgorithms()); .negotiateHashAlgorithm(info.getPreferredHashAlgorithms());

View file

@ -42,7 +42,10 @@ public final class OpenPgpKeyAttributeUtil {
continue; continue;
} }
for (int h : hashAlgos) { for (int h : hashAlgos) {
hashAlgorithms.add(HashAlgorithm.fromId(h)); HashAlgorithm algorithm = HashAlgorithm.fromId(h);
if (algorithm != null) {
hashAlgorithms.add(algorithm);
}
} }
// Exit the loop after the first key signature with hash algorithms. // Exit the loop after the first key signature with hash algorithms.
break; break;

View file

@ -42,7 +42,7 @@ public class PublicKeyParameterValidationUtil {
public static void verifyPublicKeyParameterIntegrity(PGPPrivateKey privateKey, PGPPublicKey publicKey) public static void verifyPublicKeyParameterIntegrity(PGPPrivateKey privateKey, PGPPublicKey publicKey)
throws KeyIntegrityException { throws KeyIntegrityException {
PublicKeyAlgorithm publicKeyAlgorithm = PublicKeyAlgorithm.fromId(publicKey.getAlgorithm()); PublicKeyAlgorithm publicKeyAlgorithm = PublicKeyAlgorithm.requireFromId(publicKey.getAlgorithm());
boolean valid = true; boolean valid = true;
// Algorithm specific validations // Algorithm specific validations
@ -97,7 +97,7 @@ public class PublicKeyParameterValidationUtil {
*/ */
private static boolean verifyCanSign(PGPPrivateKey privateKey, PGPPublicKey publicKey) { private static boolean verifyCanSign(PGPPrivateKey privateKey, PGPPublicKey publicKey) {
SecureRandom random = new SecureRandom(); SecureRandom random = new SecureRandom();
PublicKeyAlgorithm publicKeyAlgorithm = PublicKeyAlgorithm.fromId(publicKey.getAlgorithm()); PublicKeyAlgorithm publicKeyAlgorithm = PublicKeyAlgorithm.requireFromId(publicKey.getAlgorithm());
PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator( PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator(
ImplementationFactory.getInstance().getPGPContentSignerBuilder(publicKeyAlgorithm, HashAlgorithm.SHA256) ImplementationFactory.getInstance().getPGPContentSignerBuilder(publicKeyAlgorithm, HashAlgorithm.SHA256)
); );

View file

@ -9,6 +9,7 @@ import java.util.Collections;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.NoSuchElementException;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
@ -232,8 +233,13 @@ public final class Policy {
* @return true if algorithm is acceptable, false otherwise * @return true if algorithm is acceptable, false otherwise
*/ */
public boolean isAcceptable(int algorithmId) { public boolean isAcceptable(int algorithmId) {
SymmetricKeyAlgorithm algorithm = SymmetricKeyAlgorithm.fromId(algorithmId); try {
SymmetricKeyAlgorithm algorithm = SymmetricKeyAlgorithm.requireFromId(algorithmId);
return isAcceptable(algorithm); return isAcceptable(algorithm);
} catch (NoSuchElementException e) {
// Unknown algorithm is not acceptable
return false;
}
} }
/** /**
@ -329,8 +335,13 @@ public final class Policy {
* @return true if the hash algorithm is acceptable, false otherwise * @return true if the hash algorithm is acceptable, false otherwise
*/ */
public boolean isAcceptable(int algorithmId) { public boolean isAcceptable(int algorithmId) {
HashAlgorithm algorithm = HashAlgorithm.fromId(algorithmId); try {
HashAlgorithm algorithm = HashAlgorithm.requireFromId(algorithmId);
return isAcceptable(algorithm); return isAcceptable(algorithm);
} catch (NoSuchElementException e) {
// Unknown algorithm is not acceptable
return false;
}
} }
/** /**
@ -382,7 +393,13 @@ public final class Policy {
} }
public boolean isAcceptable(int compressionAlgorithmTag) { public boolean isAcceptable(int compressionAlgorithmTag) {
return isAcceptable(CompressionAlgorithm.fromId(compressionAlgorithmTag)); try {
CompressionAlgorithm compressionAlgorithm = CompressionAlgorithm.requireFromId(compressionAlgorithmTag);
return isAcceptable(compressionAlgorithm);
} catch (NoSuchElementException e) {
// Unknown algorithm is not acceptable
return false;
}
} }
public boolean isAcceptable(CompressionAlgorithm compressionAlgorithm) { public boolean isAcceptable(CompressionAlgorithm compressionAlgorithm) {
@ -408,7 +425,13 @@ public final class Policy {
} }
public boolean isAcceptable(int algorithmId, int bitStrength) { public boolean isAcceptable(int algorithmId, int bitStrength) {
return isAcceptable(PublicKeyAlgorithm.fromId(algorithmId), bitStrength); try {
PublicKeyAlgorithm algorithm = PublicKeyAlgorithm.requireFromId(algorithmId);
return isAcceptable(algorithm, bitStrength);
} catch (NoSuchElementException e) {
// Unknown algorithm is not acceptable
return false;
}
} }
public boolean isAcceptable(PublicKeyAlgorithm algorithm, int bitStrength) { public boolean isAcceptable(PublicKeyAlgorithm algorithm, int bitStrength) {

View file

@ -9,6 +9,7 @@ import java.util.Date;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.NoSuchElementException;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import org.bouncycastle.bcpg.sig.KeyFlags; import org.bouncycastle.bcpg.sig.KeyFlags;
@ -92,7 +93,7 @@ public abstract class SignatureValidator {
return new SignatureValidator() { return new SignatureValidator() {
@Override @Override
public void verify(PGPSignature signature) throws SignatureValidationException { public void verify(PGPSignature signature) throws SignatureValidationException {
if (!PublicKeyAlgorithm.fromId(signature.getKeyAlgorithm()).isSigningCapable()) { if (!PublicKeyAlgorithm.requireFromId(signature.getKeyAlgorithm()).isSigningCapable()) {
// subkey is not signing capable -> No need to process embedded sigs // subkey is not signing capable -> No need to process embedded sigs
return; return;
} }
@ -168,7 +169,7 @@ public abstract class SignatureValidator {
return new SignatureValidator() { return new SignatureValidator() {
@Override @Override
public void verify(PGPSignature signature) throws SignatureValidationException { public void verify(PGPSignature signature) throws SignatureValidationException {
PublicKeyAlgorithm algorithm = PublicKeyAlgorithm.fromId(signingKey.getAlgorithm()); PublicKeyAlgorithm algorithm = PublicKeyAlgorithm.requireFromId(signingKey.getAlgorithm());
int bitStrength = signingKey.getBitStrength(); int bitStrength = signingKey.getBitStrength();
if (bitStrength == -1) { if (bitStrength == -1) {
throw new SignatureValidationException("Cannot determine bit strength of signing key."); throw new SignatureValidationException("Cannot determine bit strength of signing key.");
@ -191,12 +192,15 @@ public abstract class SignatureValidator {
return new SignatureValidator() { return new SignatureValidator() {
@Override @Override
public void verify(PGPSignature signature) throws SignatureValidationException { public void verify(PGPSignature signature) throws SignatureValidationException {
HashAlgorithm hashAlgorithm = HashAlgorithm.fromId(signature.getHashAlgorithm()); try {
HashAlgorithm hashAlgorithm = HashAlgorithm.requireFromId(signature.getHashAlgorithm());
Policy.HashAlgorithmPolicy hashAlgorithmPolicy = getHashAlgorithmPolicyForSignature(signature, policy); Policy.HashAlgorithmPolicy hashAlgorithmPolicy = getHashAlgorithmPolicyForSignature(signature, policy);
if (!hashAlgorithmPolicy.isAcceptable(signature.getHashAlgorithm())) { if (!hashAlgorithmPolicy.isAcceptable(signature.getHashAlgorithm())) {
throw new SignatureValidationException("Signature uses unacceptable hash algorithm " + hashAlgorithm); throw new SignatureValidationException("Signature uses unacceptable hash algorithm " + hashAlgorithm);
} }
} catch (NoSuchElementException e) {
throw new SignatureValidationException("Signature uses unknown hash algorithm " + signature.getHashAlgorithm());
}
} }
}; };
} }
@ -255,8 +259,8 @@ public abstract class SignatureValidator {
PGPSignatureSubpacketVector hashedSubpackets = signature.getHashedSubPackets(); PGPSignatureSubpacketVector hashedSubpackets = signature.getHashedSubPackets();
for (int criticalTag : hashedSubpackets.getCriticalTags()) { for (int criticalTag : hashedSubpackets.getCriticalTags()) {
try { try {
SignatureSubpacket.fromCode(criticalTag); SignatureSubpacket.requireFromCode(criticalTag);
} catch (IllegalArgumentException e) { } catch (NoSuchElementException e) {
throw new SignatureValidationException("Signature contains unknown critical subpacket of type " + Long.toHexString(criticalTag)); throw new SignatureValidationException("Signature contains unknown critical subpacket of type " + Long.toHexString(criticalTag));
} }
} }

View file

@ -33,7 +33,7 @@ public class SignatureSubpacketsHelper {
public static SignatureSubpackets applyFrom(PGPSignatureSubpacketVector vector, SignatureSubpackets subpackets) { public static SignatureSubpackets applyFrom(PGPSignatureSubpacketVector vector, SignatureSubpackets subpackets) {
for (SignatureSubpacket subpacket : vector.toArray()) { for (SignatureSubpacket subpacket : vector.toArray()) {
org.pgpainless.algorithm.SignatureSubpacket type = org.pgpainless.algorithm.SignatureSubpacket.fromCode(subpacket.getType()); org.pgpainless.algorithm.SignatureSubpacket type = org.pgpainless.algorithm.SignatureSubpacket.requireFromCode(subpacket.getType());
switch (type) { switch (type) {
case signatureCreationTime: case signatureCreationTime:
case issuerKeyId: case issuerKeyId:
@ -102,8 +102,8 @@ public class SignatureSubpacketsHelper {
case signatureTarget: case signatureTarget:
SignatureTarget target = (SignatureTarget) subpacket; SignatureTarget target = (SignatureTarget) subpacket;
subpackets.setSignatureTarget(target.isCritical(), subpackets.setSignatureTarget(target.isCritical(),
PublicKeyAlgorithm.fromId(target.getPublicKeyAlgorithm()), PublicKeyAlgorithm.requireFromId(target.getPublicKeyAlgorithm()),
HashAlgorithm.fromId(target.getHashAlgorithm()), HashAlgorithm.requireFromId(target.getHashAlgorithm()),
target.getHashData()); target.getHashData());
break; break;
case embeddedSignature: case embeddedSignature:

View file

@ -257,7 +257,10 @@ public final class SignatureSubpacketsUtil {
PreferredAlgorithms preferences = getPreferredSymmetricAlgorithms(signature); PreferredAlgorithms preferences = getPreferredSymmetricAlgorithms(signature);
if (preferences != null) { if (preferences != null) {
for (int code : preferences.getPreferences()) { for (int code : preferences.getPreferences()) {
algorithms.add(SymmetricKeyAlgorithm.fromId(code)); SymmetricKeyAlgorithm algorithm = SymmetricKeyAlgorithm.fromId(code);
if (algorithm != null) {
algorithms.add(algorithm);
}
} }
} }
return algorithms; return algorithms;
@ -286,7 +289,10 @@ public final class SignatureSubpacketsUtil {
PreferredAlgorithms preferences = getPreferredHashAlgorithms(signature); PreferredAlgorithms preferences = getPreferredHashAlgorithms(signature);
if (preferences != null) { if (preferences != null) {
for (int code : preferences.getPreferences()) { for (int code : preferences.getPreferences()) {
algorithms.add(HashAlgorithm.fromId(code)); HashAlgorithm algorithm = HashAlgorithm.fromId(code);
if (algorithm != null) {
algorithms.add(algorithm);
}
} }
} }
return algorithms; return algorithms;
@ -315,7 +321,10 @@ public final class SignatureSubpacketsUtil {
PreferredAlgorithms preferences = getPreferredCompressionAlgorithms(signature); PreferredAlgorithms preferences = getPreferredCompressionAlgorithms(signature);
if (preferences != null) { if (preferences != null) {
for (int code : preferences.getPreferences()) { for (int code : preferences.getPreferences()) {
algorithms.add(CompressionAlgorithm.fromId(code)); CompressionAlgorithm algorithm = CompressionAlgorithm.fromId(code);
if (algorithm != null) {
algorithms.add(algorithm);
}
} }
} }
return algorithms; return algorithms;

View file

@ -24,7 +24,7 @@ public class SessionKey {
* @param sessionKey BC session key * @param sessionKey BC session key
*/ */
public SessionKey(@Nonnull PGPSessionKey sessionKey) { public SessionKey(@Nonnull PGPSessionKey sessionKey) {
this(SymmetricKeyAlgorithm.fromId(sessionKey.getAlgorithm()), sessionKey.getKey()); this(SymmetricKeyAlgorithm.requireFromId(sessionKey.getAlgorithm()), sessionKey.getKey());
} }
/** /**

View file

@ -6,20 +6,37 @@ package org.pgpainless.algorithm;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.util.NoSuchElementException;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
public class FeatureTest { public class FeatureTest {
@Test
public void testAll() {
for (Feature feature : Feature.values()) {
assertEquals(feature, Feature.fromId(feature.getFeatureId()));
assertEquals(feature, Feature.requireFromId(feature.getFeatureId()));
}
}
@Test @Test
public void testModificationDetection() { public void testModificationDetection() {
Feature modificationDetection = Feature.MODIFICATION_DETECTION; Feature modificationDetection = Feature.MODIFICATION_DETECTION;
assertEquals(0x01, modificationDetection.getFeatureId()); assertEquals(0x01, modificationDetection.getFeatureId());
assertEquals(modificationDetection, Feature.fromId((byte) 0x01)); assertEquals(modificationDetection, Feature.fromId((byte) 0x01));
assertEquals(modificationDetection, Feature.requireFromId((byte) 0x01));
} }
@Test @Test
public void testFromInvalidIdIsNull() { public void testFromInvalidIdIsNull() {
assertNull(Feature.fromId((byte) 0x99)); assertNull(Feature.fromId((byte) 0x99));
} }
@Test
public void testRequireFromInvalidThrows() {
assertThrows(NoSuchElementException.class, () -> Feature.requireFromId((byte) 0x99));
}
} }

View file

@ -64,7 +64,7 @@ public class SignatureStructureTest {
@Test @Test
public void testGetHashAlgorithm() { public void testGetHashAlgorithm() {
assertEquals(HashAlgorithm.SHA256, HashAlgorithm.fromId(signature.getHashAlgorithm())); assertEquals(HashAlgorithm.SHA256, HashAlgorithm.requireFromId(signature.getHashAlgorithm()));
} }
@Test @Test

View file

@ -70,7 +70,7 @@ public class DecryptImpl implements Decrypt {
public DecryptImpl withSessionKey(SessionKey sessionKey) throws SOPGPException.UnsupportedOption { public DecryptImpl withSessionKey(SessionKey sessionKey) throws SOPGPException.UnsupportedOption {
consumerOptions.setSessionKey( consumerOptions.setSessionKey(
new org.pgpainless.util.SessionKey( new org.pgpainless.util.SessionKey(
SymmetricKeyAlgorithm.fromId(sessionKey.getAlgorithm()), SymmetricKeyAlgorithm.requireFromId(sessionKey.getAlgorithm()),
sessionKey.getKey())); sessionKey.getKey()));
return this; return this;
} }