Skip to content

Add missing methods for OpenPGP v6 API #2105

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 22 additions & 22 deletions pg/src/main/java/org/bouncycastle/bcpg/PublicKeyUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,26 +30,26 @@ public static boolean isSigningAlgorithm(int publicKeyAlgorithm)
}
}

// /**
// * Return true, if the public key algorithm that corresponds to the given ID is capable of encryption.
// * @param publicKeyAlgorithm public key algorithm id
// * @return true if algorithm can encrypt
// */
// public static boolean isEncryptionAlgorithm(int publicKeyAlgorithm)
// {
// switch (publicKeyAlgorithm)
// {
// case PublicKeyAlgorithmTags.RSA_GENERAL:
// case PublicKeyAlgorithmTags.RSA_ENCRYPT:
// case PublicKeyAlgorithmTags.ELGAMAL_ENCRYPT:
// case PublicKeyAlgorithmTags.ECDH:
// case PublicKeyAlgorithmTags.ELGAMAL_GENERAL:
// case PublicKeyAlgorithmTags.DIFFIE_HELLMAN:
// case PublicKeyAlgorithmTags.X25519:
// case PublicKeyAlgorithmTags.X448:
// return true;
// default:
// return false;
// }
// }
/**
* Return true, if the public key algorithm that corresponds to the given ID is capable of encryption.
* @param publicKeyAlgorithm public key algorithm id
* @return true if algorithm can encrypt
*/
public static boolean isEncryptionAlgorithm(int publicKeyAlgorithm)
{
switch (publicKeyAlgorithm)
{
case PublicKeyAlgorithmTags.RSA_GENERAL:
case PublicKeyAlgorithmTags.RSA_ENCRYPT:
case PublicKeyAlgorithmTags.ELGAMAL_ENCRYPT:
case PublicKeyAlgorithmTags.ECDH:
case PublicKeyAlgorithmTags.ELGAMAL_GENERAL:
case PublicKeyAlgorithmTags.DIFFIE_HELLMAN:
case PublicKeyAlgorithmTags.X25519:
case PublicKeyAlgorithmTags.X448:
return true;
default:
return false;
}
}
}
35 changes: 35 additions & 0 deletions pg/src/main/java/org/bouncycastle/bcpg/SignaturePacket.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.bouncycastle.bcpg.sig.IssuerFingerprint;
import org.bouncycastle.bcpg.sig.IssuerKeyID;
import org.bouncycastle.bcpg.sig.SignatureCreationTime;
import org.bouncycastle.openpgp.PGPSignatureSubpacketVector;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.Pack;
import org.bouncycastle.util.io.Streams;
Expand Down Expand Up @@ -446,6 +447,40 @@ public SignaturePacket(
}
}

public static SignaturePacket copyOfWith(SignaturePacket packet, SignatureSubpacket[] unhashedSubpackets)
{
if (packet.getVersion() == SignaturePacket.VERSION_6)
{
return new SignaturePacket(
packet.getVersion(),
packet.getSignatureType(),
packet.getKeyID(),
packet.getKeyAlgorithm(),
packet.getHashAlgorithm(),
packet.getHashedSubPackets(),
unhashedSubpackets,
packet.getFingerPrint(),
packet.getSignatureBytes(),
packet.getSalt()
);
}
else
{
return new SignaturePacket(
packet.getVersion(),
packet.hasNewPacketFormat(),
packet.getSignatureType(),
packet.getKeyID(),
packet.getKeyAlgorithm(),
packet.getHashAlgorithm(),
packet.getHashedSubPackets(),
unhashedSubpackets,
packet.getFingerPrint(),
packet.getSignature()
);
}
}

/**
* get the version number
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,11 @@ public PGPEncryptedData get(
return (PGPEncryptedData)methods.get(index);
}

public InputStreamPacket getEncryptedData()
{
return data;
}

/**
* Gets the number of encryption methods in this list.
*/
Expand Down
10 changes: 10 additions & 0 deletions pg/src/main/java/org/bouncycastle/openpgp/PGPKeyRing.java
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,16 @@ static void readUserIDs(
}
}

/**
* Return the {@link KeyIdentifier} of this key rings primary key.
*
* @return primary key identifier
*/
public KeyIdentifier getKeyIdentifier()
{
return getPublicKey().getKeyIdentifier();
}

/**
* Return the first public key in the ring. In the case of a {@link PGPSecretKeyRing}
* this is also the public key of the master key pair.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@

import org.bouncycastle.bcpg.BCPGInputStream;
import org.bouncycastle.bcpg.PacketTags;
import org.bouncycastle.bcpg.TrustPacket;
import org.bouncycastle.bcpg.UnknownPacket;
import org.bouncycastle.bcpg.UnsupportedPacketVersionException;
import org.bouncycastle.openpgp.operator.KeyFingerPrintCalculator;
import org.bouncycastle.util.Iterable;

/**
* General class for reading a PGP object stream.
Expand Down Expand Up @@ -141,6 +141,8 @@ public Object nextObject()
return new PGPCompressedData(in);
case PacketTags.LITERAL_DATA:
return new PGPLiteralData(in);
case PacketTags.TRUST:
return new PGPTrust(in);
case PacketTags.PUBLIC_KEY_ENC_SESSION:
case PacketTags.SYMMETRIC_KEY_ENC_SESSION:
case PacketTags.SYMMETRIC_KEY_ENC:
Expand Down
11 changes: 9 additions & 2 deletions pg/src/main/java/org/bouncycastle/openpgp/PGPPublicKey.java
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,14 @@ public Iterator<String> getUserIDs()
{
if (ids.get(i) instanceof UserIDPacket)
{
temp.add(((UserIDPacket)ids.get(i)).getID());
try
{
temp.add(((UserIDPacket) ids.get(i)).getID());
}
catch (IllegalArgumentException e)
{
// Skip non-UTF8 user-ids
}
}
}

Expand Down Expand Up @@ -1157,7 +1164,7 @@ public static PGPPublicKey join(
}

// key signatures
joinPgpSignatureList(copy.keySigs, keySigs, true, true);
joinPgpSignatureList(copy.keySigs, keySigs, false, true);

// user-ids and id sigs
for (int idIdx = 0; idIdx < copy.ids.size(); idIdx++)
Expand Down
6 changes: 3 additions & 3 deletions pg/src/main/java/org/bouncycastle/openpgp/PGPSecretKey.java
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ public PGPSecretKey(
//
// generate the certification
//
PGPSignatureGenerator sGen = new PGPSignatureGenerator(certificationSignerBuilder);
PGPSignatureGenerator sGen = new PGPSignatureGenerator(certificationSignerBuilder, masterKeyPair.getPublicKey());

sGen.init(PGPSignature.SUBKEY_BINDING, masterKeyPair.getPrivateKey());

Expand All @@ -302,7 +302,7 @@ public PGPSecretKey(
{
if (hashedPcks == null)
{
PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator(certificationSignerBuilder);
PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator(certificationSignerBuilder, keyPair.getPublicKey());

signatureGenerator.init(PGPSignature.PRIMARYKEY_BINDING, keyPair.getPrivateKey());

Expand Down Expand Up @@ -382,7 +382,7 @@ private static PGPPublicKey certifiedPublicKey(

try
{
sGen = new PGPSignatureGenerator(certificationSignerBuilder);
sGen = new PGPSignatureGenerator(certificationSignerBuilder, keyPair.getPublicKey());
}
catch (Exception e)
{
Expand Down
13 changes: 1 addition & 12 deletions pg/src/main/java/org/bouncycastle/openpgp/PGPSignature.java
Original file line number Diff line number Diff line change
Expand Up @@ -1033,18 +1033,7 @@ public static PGPSignature join(PGPSignature sig1, PGPSignature sig2)

SignatureSubpacket[] unhashed = (SignatureSubpacket[])merged.toArray(new SignatureSubpacket[0]);
return new PGPSignature(
new SignaturePacket(
sig1.getVersion(),
sig1.sigPck.hasNewPacketFormat(),
sig1.getSignatureType(),
sig1.getKeyID(),
sig1.getKeyAlgorithm(),
sig1.getHashAlgorithm(),
sig1.getHashedSubPackets().packets,
unhashed,
sig1.getDigestPrefix(),
sig1.sigPck.getSignature()
)
SignaturePacket.copyOfWith(sig1.sigPck, unhashed)
);
}
}
36 changes: 36 additions & 0 deletions pg/src/main/java/org/bouncycastle/openpgp/PGPTrust.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package org.bouncycastle.openpgp;

import org.bouncycastle.bcpg.BCPGInputStream;
import org.bouncycastle.bcpg.TrustPacket;

import java.io.IOException;
import java.util.Arrays;

public class PGPTrust
{

private final TrustPacket packet;

public PGPTrust(TrustPacket packet)
{
this.packet = packet;
}

public PGPTrust(BCPGInputStream inputStream)
throws IOException
{
this((TrustPacket) inputStream.readPacket());
}

public TrustPacket getPacket()
{
return packet;
}

public byte[] getLevelAndTrust()
{
return Arrays.copyOf(
packet.getLevelAndTrustAmount(),
packet.getLevelAndTrustAmount().length);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
package org.bouncycastle.openpgp.api;

import org.bouncycastle.bcpg.AEADEncDataPacket;
import org.bouncycastle.bcpg.InputStreamPacket;
import org.bouncycastle.bcpg.SymmetricEncDataPacket;
import org.bouncycastle.bcpg.SymmetricEncIntegrityPacket;
import org.bouncycastle.bcpg.UnsupportedPacketVersionException;
import org.bouncycastle.openpgp.PGPEncryptedDataList;
import org.bouncycastle.openpgp.PGPException;

/**
* Encryption Mode.
*/
Expand Down Expand Up @@ -34,4 +42,58 @@ public enum EncryptedDataPacketType
* Support for this feature is signalled using {@link org.bouncycastle.bcpg.sig.Features#FEATURE_AEAD_ENCRYPTED_DATA}.
*/
LIBREPGP_OED // "v5"
;

/**
* Detect the type of the PGPEncryptedDataList's encrypted data packet.
*
* @param encDataList encrypted data list
* @return encrypted data packet type
* @throws PGPException if an unexpected data packet is encountered.
*/
public static EncryptedDataPacketType of(PGPEncryptedDataList encDataList)
throws PGPException
{
return of(encDataList.getEncryptedData());
}

/**
* Detect the type the provided encrypted data packet.
*
* @param encData encrypted data packet
* @return encrypted data packet type
* @throws PGPException if an unexpected data packet is encountered.
*/
public static EncryptedDataPacketType of(InputStreamPacket encData)
throws PGPException
{
if (encData instanceof SymmetricEncIntegrityPacket)
{
SymmetricEncIntegrityPacket seipd = (SymmetricEncIntegrityPacket) encData;
if (seipd.getVersion() == SymmetricEncIntegrityPacket.VERSION_1)
{
return SEIPDv1;
}
else if (seipd.getVersion() == SymmetricEncIntegrityPacket.VERSION_2)
{
return SEIPDv2;
}
else
{
throw new UnsupportedPacketVersionException("Symmetrically-Encrypted Integrity-Protected Data Packet of unknown version encountered: " + seipd.getVersion());
}
}
else if (encData instanceof AEADEncDataPacket)
{
return LIBREPGP_OED;
}
else if (encData instanceof SymmetricEncDataPacket)
{
return SED;
}
else
{
throw new PGPException("Unexpected packet type: " + encData.getClass().getName());
}
}
}
Loading