Skip to content

Commit

Permalink
Refactor SignaturePacket class
Browse files Browse the repository at this point in the history
  • Loading branch information
vanitasvitae committed May 15, 2023
1 parent 223dfbb commit d12240b
Showing 1 changed file with 174 additions and 141 deletions.
315 changes: 174 additions & 141 deletions pg/src/main/java/org/bouncycastle/bcpg/SignaturePacket.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

import org.bouncycastle.bcpg.sig.IssuerKeyID;
import org.bouncycastle.bcpg.sig.SignatureCreationTime;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.io.Streams;

Expand All @@ -19,6 +18,7 @@ public class SignaturePacket
{
public static final int VERSION_3 = 3;
public static final int VERSION_4 = 4;
public static final int VERSION_5 = 5;
public static final int VERSION_6 = 6;

private int version;
Expand All @@ -39,172 +39,205 @@ public class SignaturePacket
throws IOException
{
version = in.read();

if (version == VERSION_3 || version == 2) // TODO: Version 2 is not specified. Clarify?

// TODO: Version 2 is not specified. Clarify?
if (version == VERSION_3 || version == 2)
{
int l = in.read();

signatureType = in.read();
creationTime = (((long)in.read() << 24) | (in.read() << 16) | (in.read() << 8) | in.read()) * 1000;
keyID |= (long)in.read() << 56;
keyID |= (long)in.read() << 48;
keyID |= (long)in.read() << 40;
keyID |= (long)in.read() << 32;
keyID |= (long)in.read() << 24;
keyID |= (long)in.read() << 16;
keyID |= (long)in.read() << 8;
keyID |= in.read();
keyAlgorithm = in.read();
hashAlgorithm = in.read();
readVersion2_3Packet(in);
}
else if (version == VERSION_4 || version == VERSION_6)
else if (version == VERSION_4 || version == VERSION_5)
{
signatureType = in.read();
keyAlgorithm = in.read();
hashAlgorithm = in.read();

int hashedLength = readLength(in);
byte[] hashed = new byte[hashedLength];

in.readFully(hashed);
readVersion4_5Packet(in);
}
else if (version == VERSION_6)
{
readVersion6Packet(in);
}
else
{
Streams.drain(in);
throw new UnsupportedPacketVersionException("unsupported version: " + version);
}
}

//
// read the signature sub packet data.
//
SignatureSubpacket sub;
SignatureSubpacketInputStream sIn = new SignatureSubpacketInputStream(
new ByteArrayInputStream(hashed));
private void readVersion2_3Packet(BCPGInputStream in) throws IOException {
int l = in.read();

signatureType = in.read();
creationTime = (((long) in.read() << 24) | (in.read() << 16) | (in.read() << 8) | in.read()) * 1000;
keyID |= (long) in.read() << 56;
keyID |= (long) in.read() << 48;
keyID |= (long) in.read() << 40;
keyID |= (long) in.read() << 32;
keyID |= (long) in.read() << 24;
keyID |= (long) in.read() << 16;
keyID |= (long) in.read() << 8;
keyID |= in.read();
keyAlgorithm = in.read();
hashAlgorithm = in.read();

// 2 byte fp
readFingerprint(in);

readSignature(in);
}

Vector v = new Vector();
while ((sub = sIn.readPacket()) != null)
{
v.addElement(sub);
}

hashedData = new SignatureSubpacket[v.size()];

for (int i = 0; i != hashedData.length; i++)
private void readVersion4_5Packet(BCPGInputStream in) throws IOException {
signatureType = in.read();
keyAlgorithm = in.read();
hashAlgorithm = in.read();

hashedData = readSubpackets(in, true);
unhashedData = readSubpackets(in, false);

// 2 byte fp
readFingerprint(in);
readSignature(in);
}


private void readVersion6Packet(BCPGInputStream in) throws IOException {
signatureType = in.read();
keyAlgorithm = in.read();
hashAlgorithm = in.read();

hashedData = readSubpackets(in, true);
unhashedData = readSubpackets(in, false);

// 2 byte fp
readFingerprint(in);

readSalt(in);

readSignature(in);
}

private SignatureSubpacket[] readSubpackets(BCPGInputStream in, boolean isHashed)
throws IOException
{
int length = readLength(in);
byte[] data = new byte[length];

in.readFully(data);

//
// read the signature sub packet data.
//
SignatureSubpacket sub;
SignatureSubpacketInputStream sIn = new SignatureSubpacketInputStream(
new ByteArrayInputStream(data));

Vector<SignatureSubpacket> v = new Vector<SignatureSubpacket>();
while ((sub = sIn.readPacket()) != null)
{
v.addElement(sub);
}

SignatureSubpacket[] subpackets = new SignatureSubpacket[v.size()];

for (int i = 0; i != subpackets.length; i++)
{
SignatureSubpacket p = v.elementAt(i);
if (isHashed)
{
SignatureSubpacket p = (SignatureSubpacket)v.elementAt(i);
if (p instanceof IssuerKeyID)
{
keyID = ((IssuerKeyID)p).getKeyID();
keyID = ((IssuerKeyID) p).getKeyID();
}
else if (p instanceof SignatureCreationTime)
{
creationTime = ((SignatureCreationTime)p).getTime().getTime();
creationTime = ((SignatureCreationTime) p).getTime().getTime();
}

hashedData[i] = p;
}

int unhashedLength = readLength(in);
byte[] unhashed = new byte[unhashedLength];

in.readFully(unhashed);

sIn = new SignatureSubpacketInputStream(
new ByteArrayInputStream(unhashed));

v.removeAllElements();
while ((sub = sIn.readPacket()) != null)
{
v.addElement(sub);
}

unhashedData = new SignatureSubpacket[v.size()];

for (int i = 0; i != unhashedData.length; i++)
else
{
SignatureSubpacket p = (SignatureSubpacket)v.elementAt(i);
if (p instanceof IssuerKeyID)
if (p instanceof IssuerKeyID && keyID == 0)
{
keyID = ((IssuerKeyID)p).getKeyID();
keyID = ((IssuerKeyID) p).getKeyID();
}

unhashedData[i] = p;
}
}
else
{
Streams.drain(in);

throw new UnsupportedPacketVersionException("unsupported version: " + version);
subpackets[i] = p;
}


return subpackets;
}

private void readFingerprint(BCPGInputStream in) throws IOException {
fingerPrint = new byte[2];
in.readFully(fingerPrint);
}

if (version == VERSION_6)
{
int saltSize = in.read();

int expectedSaltSize = getSaltSize(hashAlgorithm);
if (expectedSaltSize != -1 && saltSize != getSaltSize(hashAlgorithm)) {
throw new IOException("Salt length mismatch. Expected " + expectedSaltSize + " bytes, but signature indicates " + saltSize);
}
private void readSalt(BCPGInputStream in) throws IOException {
int saltSize = in.read();

salt = new byte[saltSize];
in.readFully(salt);
int expectedSaltSize = getSaltSize(hashAlgorithm);
if (expectedSaltSize != -1 && saltSize != getSaltSize(hashAlgorithm)) {
throw new IOException("Salt length mismatch. Expected " + expectedSaltSize + " bytes, but signature indicates " + saltSize);
}


salt = new byte[saltSize];
in.readFully(salt);
}

private void readSignature(BCPGInputStream in) throws IOException {
switch (keyAlgorithm)
{
case RSA_GENERAL:
case RSA_SIGN:
MPInteger v = new MPInteger(in);

signature = new MPInteger[1];
signature[0] = v;
break;
case DSA:
MPInteger r = new MPInteger(in);
MPInteger s = new MPInteger(in);

signature = new MPInteger[2];
signature[0] = r;
signature[1] = s;
break;
case ELGAMAL_ENCRYPT: // yep, this really does happen sometimes.
case ELGAMAL_GENERAL:
MPInteger p = new MPInteger(in);
MPInteger g = new MPInteger(in);
MPInteger y = new MPInteger(in);

signature = new MPInteger[3];
signature[0] = p;
signature[1] = g;
signature[2] = y;
break;
case ECDSA:
case EDDSA_LEGACY:
MPInteger ecR = new MPInteger(in);
MPInteger ecS = new MPInteger(in);

signature = new MPInteger[2];
signature[0] = ecR;
signature[1] = ecS;
break;
case Ed25519:
signature = null;
signatureEncoding = new byte[64];
in.readFully(signatureEncoding);
break;
case Ed448:
signature = null;
signatureEncoding = new byte[114];
in.readFully(signatureEncoding);
break;
default:
if (keyAlgorithm >= PublicKeyAlgorithmTags.EXPERIMENTAL_1 && keyAlgorithm <= PublicKeyAlgorithmTags.EXPERIMENTAL_11)
{
case RSA_GENERAL:
case RSA_SIGN:
MPInteger v = new MPInteger(in);

signature = new MPInteger[1];
signature[0] = v;
break;
case DSA:
MPInteger r = new MPInteger(in);
MPInteger s = new MPInteger(in);

signature = new MPInteger[2];
signature[0] = r;
signature[1] = s;
break;
case ELGAMAL_ENCRYPT: // yep, this really does happen sometimes.
case ELGAMAL_GENERAL:
MPInteger p = new MPInteger(in);
MPInteger g = new MPInteger(in);
MPInteger y = new MPInteger(in);

signature = new MPInteger[3];
signature[0] = p;
signature[1] = g;
signature[2] = y;
break;
case ECDSA:
case EDDSA_LEGACY:
MPInteger ecR = new MPInteger(in);
MPInteger ecS = new MPInteger(in);

signature = new MPInteger[2];
signature[0] = ecR;
signature[1] = ecS;
break;
case Ed25519:
signature = null;
signatureEncoding = Streams.readAll(in);
}
else
{
throw new IOException("unknown signature key algorithm: " + keyAlgorithm);
}
signatureEncoding = new byte[64];
in.readFully(signatureEncoding);
break;
case Ed448:
signature = null;
signatureEncoding = new byte[114];
in.readFully(signatureEncoding);
break;
default:
if (keyAlgorithm >= PublicKeyAlgorithmTags.EXPERIMENTAL_1 && keyAlgorithm <= PublicKeyAlgorithmTags.EXPERIMENTAL_11)
{
signature = null;
signatureEncoding = Streams.readAll(in);
}
else
{
throw new IOException("unknown signature key algorithm: " + keyAlgorithm);
}
}
}

Expand Down Expand Up @@ -527,7 +560,7 @@ public void encode(
pOut.write(keyAlgorithm);
pOut.write(hashAlgorithm);
}
else if (version == VERSION_4 || version == VERSION_6)
else if (version == VERSION_4 || version == VERSION_5 || version == VERSION_6)
{
pOut.write(signatureType);
pOut.write(keyAlgorithm);
Expand Down

0 comments on commit d12240b

Please sign in to comment.