Skip to content

Commit 5bb48a0

Browse files
committed
Merge branch '1844-openpgp-signature-join' into 'main'
1844 Improve comparison logic during signature joining See merge request root/bc-java!37
2 parents 27eb23c + a9e1bc2 commit 5bb48a0

File tree

2 files changed

+42
-26
lines changed

2 files changed

+42
-26
lines changed

pg/src/main/java/org/bouncycastle/openpgp/PGPPublicKey.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public class PGPPublicKey
4747
List<List<PGPSignature>> idSigs = new ArrayList<List<PGPSignature>>();
4848

4949
List<PGPSignature> subSigs = null;
50-
50+
5151
private KeyIdentifier keyIdentifier;
5252
private int keyStrength;
5353

@@ -150,7 +150,7 @@ public PGPPublicKey(PublicKeyPacket publicKeyPacket, KeyFingerPrintCalculator fi
150150
this.publicPk = key.publicPk;
151151
this.trustPk = trust;
152152
this.subSigs = subSigs;
153-
153+
154154
this.keyStrength = key.keyStrength;
155155
this.keyIdentifier = key.keyIdentifier;
156156
}
@@ -1216,7 +1216,8 @@ private static void joinPgpSignatureList(List<PGPSignature> source,
12161216
for (int i = 0; isNotNull && i < rlt.size(); i++)
12171217
{
12181218
PGPSignature existingSubSig = (PGPSignature)rlt.get(i);
1219-
if (PGPSignature.isSignatureEncodingEqual(existingSubSig, copySubSig))
1219+
if (existingSubSig.getVersion() == copySubSig.getVersion() &&
1220+
PGPSignature.isSignatureEncodingEqual(existingSubSig, copySubSig))
12201221
{
12211222
found = true;
12221223
// join existing sig with copy to apply modifications in unhashed subpackets

pg/src/main/java/org/bouncycastle/openpgp/PGPSignature.java

Lines changed: 38 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public class PGPSignature
4545
* This signature type is used to create data signatures.
4646
*
4747
* @see <a href="https://www.rfc-editor.org/rfc/rfc9580.html#name-binary-signature-type-id-0x">
48-
* RFC9580 - Binary Signature of a Document</a>
48+
* RFC9580 - Binary Signature of a Document</a>
4949
*/
5050
public static final int BINARY_DOCUMENT = 0x00;
5151

@@ -56,15 +56,15 @@ public class PGPSignature
5656
* This signature type is used to create data signatures.
5757
*
5858
* @see <a href="https://www.rfc-editor.org/rfc/rfc9580.html#name-text-signature-type-id-0x01">
59-
* RFC9580 - Text Signature of a Canonical Document</a>
59+
* RFC9580 - Text Signature of a Canonical Document</a>
6060
*/
6161
public static final int CANONICAL_TEXT_DOCUMENT = 0x01;
6262

6363
/**
6464
* The signature is made only over its own signature subpackets.
6565
*
6666
* @see <a href="https://www.rfc-editor.org/rfc/rfc9580.html#name-standalone-signature-type-i">
67-
* RFC9580 - Standalone Signature</a>
67+
* RFC9580 - Standalone Signature</a>
6868
*/
6969
public static final int STAND_ALONE = 0x02;
7070

@@ -77,7 +77,7 @@ public class PGPSignature
7777
* of a third party.
7878
*
7979
* @see <a href="https://www.rfc-editor.org/rfc/rfc9580.html#name-generic-certification-signa">
80-
* RFC9580 - Generic Certification Signature of a User ID and Public Key Packet</a>
80+
* RFC9580 - Generic Certification Signature of a User ID and Public Key Packet</a>
8181
*/
8282
public static final int DEFAULT_CERTIFICATION = 0x10;
8383

@@ -89,7 +89,7 @@ public class PGPSignature
8989
* of a third party.
9090
*
9191
* @see <a href="https://www.rfc-editor.org/rfc/rfc9580.html#name-persona-certification-signa">
92-
* RFC9580 - Persona Certification Signature of a User ID and Public Key Packet</a>
92+
* RFC9580 - Persona Certification Signature of a User ID and Public Key Packet</a>
9393
*/
9494
public static final int NO_CERTIFICATION = 0x11;
9595

@@ -102,7 +102,7 @@ public class PGPSignature
102102
* of a third party.
103103
*
104104
* @see <a href="https://www.rfc-editor.org/rfc/rfc9580.html#name-casual-certification-signat">
105-
* RFC9580 - Casual Certification of a User ID an Public Key Packet</a>
105+
* RFC9580 - Casual Certification of a User ID an Public Key Packet</a>
106106
*/
107107
public static final int CASUAL_CERTIFICATION = 0x12;
108108

@@ -114,7 +114,7 @@ public class PGPSignature
114114
* of a third party.
115115
*
116116
* @see <a href="https://www.rfc-editor.org/rfc/rfc9580.html#name-positive-certification-sign">
117-
* RFC9580 - Positive Certification Signature of a User ID and Public Key Packet</a>
117+
* RFC9580 - Positive Certification Signature of a User ID and Public Key Packet</a>
118118
*/
119119
public static final int POSITIVE_CERTIFICATION = 0x13;
120120

@@ -123,7 +123,7 @@ public class PGPSignature
123123
* This signature type is used to bind a subkey to the primary key of a certificate.
124124
*
125125
* @see <a href="https://www.rfc-editor.org/rfc/rfc9580.html#name-subkey-binding-signature-ty">
126-
* RFC9580 - Subkey Binding Signature</a>
126+
* RFC9580 - Subkey Binding Signature</a>
127127
*/
128128
public static final int SUBKEY_BINDING = 0x18;
129129

@@ -133,7 +133,7 @@ public class PGPSignature
133133
* a claim by the subkey, stating that it is in fact a subkey of the primary key.
134134
*
135135
* @see <a href="https://www.rfc-editor.org/rfc/rfc9580.html#name-primary-key-binding-signatu">
136-
* RFC9580 - Primary Key Binding Signature</a>
136+
* RFC9580 - Primary Key Binding Signature</a>
137137
*/
138138
public static final int PRIMARYKEY_BINDING = 0x19;
139139

@@ -144,23 +144,23 @@ public class PGPSignature
144144
* Issued as a signature over a third-party certificate, it can be used to mark said certificate as a CA.
145145
*
146146
* @see <a href="https://www.rfc-editor.org/rfc/rfc9580.html#name-direct-key-signature-type-i">
147-
* RFC9580 - Direct Key Signature</a>
147+
* RFC9580 - Direct Key Signature</a>
148148
*/
149149
public static final int DIRECT_KEY = 0x1f;
150150

151151
/**
152152
* The signature is used to revoke a primary key (and in turn the whole certificate with all its subkeys).
153153
*
154154
* @see <a href="https://www.rfc-editor.org/rfc/rfc9580.html#name-key-revocation-signature-ty">
155-
* RFC9580 - Key Revocation Signature</a>
155+
* RFC9580 - Key Revocation Signature</a>
156156
*/
157157
public static final int KEY_REVOCATION = 0x20;
158158

159159
/**
160160
* The signature is used to revoke the binding of a particular subkey.
161161
*
162162
* @see <a href="https://www.rfc-editor.org/rfc/rfc9580.html#name-subkey-revocation-signature">
163-
* RFC9580 - Subkey Revocation Signature</a>
163+
* RFC9580 - Subkey Revocation Signature</a>
164164
*/
165165
public static final int SUBKEY_REVOCATION = 0x28;
166166

@@ -172,15 +172,15 @@ public class PGPSignature
172172
* Issued over a third-party certificate, it revokes the attestation of the third-party's claim.
173173
*
174174
* @see <a href="https://www.rfc-editor.org/rfc/rfc9580.html#name-certification-revocation-si">
175-
* RFC9580 - Certification Revocation Signature</a>
175+
* RFC9580 - Certification Revocation Signature</a>
176176
*/
177177
public static final int CERTIFICATION_REVOCATION = 0x30;
178178

179179
/**
180180
* The signature is only meaningful for the timestamp contained in it.
181181
*
182182
* @see <a href="https://www.rfc-editor.org/rfc/rfc9580.html#name-timestamp-signature-type-id">
183-
* RFC9580 - Timestamp Signature</a>
183+
* RFC9580 - Timestamp Signature</a>
184184
*/
185185
public static final int TIMESTAMP = 0x40;
186186

@@ -191,7 +191,7 @@ public class PGPSignature
191191
* to prevent certificate flooding.
192192
*
193193
* @see <a href="https://www.rfc-editor.org/rfc/rfc9580.html#name-third-party-confirmation-si">
194-
* RFC9580 - Third-Party Confirmation Signature/a>
194+
* RFC9580 - Third-Party Confirmation Signature/a>
195195
*/
196196
public static final int THIRD_PARTY_CONFIRMATION = 0x50;
197197

@@ -212,6 +212,7 @@ private static SignaturePacket cast(Packet packet)
212212

213213
/**
214214
* Parse a {@link PGPSignature} from an OpenPGP packet input stream.
215+
*
215216
* @param pIn packet input stream
216217
* @throws IOException
217218
* @throws PGPException
@@ -302,7 +303,7 @@ public boolean isCertification()
302303
* Initialize the signature for verification.
303304
*
304305
* @param verifierBuilderProvider provide the implementation for signature verification
305-
* @param pubKey issuer public key
306+
* @param pubKey issuer public key
306307
* @throws PGPException
307308
*/
308309
public void init(PGPContentVerifierBuilderProvider verifierBuilderProvider, PGPPublicKey pubKey)
@@ -334,7 +335,7 @@ PGPContentVerifierBuilder createVerifierProvider(PGPContentVerifierBuilderProvid
334335
return verifierBuilderProvider.get(sigPck.getKeyAlgorithm(), sigPck.getHashAlgorithm());
335336
}
336337

337-
void init(PGPContentVerifier verifier)
338+
void init(PGPContentVerifier verifier)
338339
throws PGPException
339340
{
340341
this.verifier = verifier;
@@ -362,7 +363,7 @@ private void checkSaltSize()
362363
}
363364

364365
private void updateWithSalt()
365-
throws PGPException
366+
throws PGPException
366367
{
367368
if (getVersion() == SignaturePacket.VERSION_6)
368369
{
@@ -382,6 +383,7 @@ private void updateWithSalt()
382383
* Note: The fact that this method returned <pre>true</pre> does not yet mean that the signature is valid.
383384
* A correct signature may very well be expired, the issuer key may be revoked, etc.
384385
* All these constraints are not checked by this method.
386+
*
385387
* @return true if the signature is correct
386388
* @throws PGPException
387389
*/
@@ -599,10 +601,10 @@ boolean doVerifyCertification(
599601

600602
/**
601603
* Return the type id of the signature.
602-
* @see <a href="https://www.rfc-editor.org/rfc/rfc9580.html#name-signature-types">
603-
* RFC9580 - Signature Types</a>
604604
*
605605
* @return type id
606+
* @see <a href="https://www.rfc-editor.org/rfc/rfc9580.html#name-signature-types">
607+
* RFC9580 - Signature Types</a>
606608
*/
607609
public int getSignatureType()
608610
{
@@ -670,13 +672,13 @@ private List<KeyIdentifier> extractKeyIdentifiers(SignatureSubpacket[] subpacket
670672
SignatureSubpacket s = subpackets[idx];
671673
if (s instanceof IssuerFingerprint)
672674
{
673-
IssuerFingerprint issuer = (IssuerFingerprint) s;
675+
IssuerFingerprint issuer = (IssuerFingerprint)s;
674676
identifiers.add(new KeyIdentifier(issuer.getFingerprint()));
675677
}
676678

677679
if (s instanceof IssuerKeyID)
678680
{
679-
IssuerKeyID issuer = (IssuerKeyID) s;
681+
IssuerKeyID issuer = (IssuerKeyID)s;
680682
identifiers.add(new KeyIdentifier(issuer.getKeyID()));
681683
}
682684
}
@@ -747,6 +749,7 @@ private PGPSignatureSubpacketVector createSubpacketVector(SignatureSubpacket[] p
747749

748750
/**
749751
* Return the salt of a v6 signature.
752+
*
750753
* @return salt
751754
*/
752755
byte[] getSalt()
@@ -757,6 +760,7 @@ byte[] getSalt()
757760
/**
758761
* Return the cryptographic raw signature contained in the OpenPGP signature packet.
759762
* The value is dependent on the signing algorithm.
763+
*
760764
* @return cryptographic signature
761765
* @throws PGPException
762766
*/
@@ -815,6 +819,7 @@ else if (getKeyAlgorithm() == PublicKeyAlgorithmTags.EDDSA_LEGACY)
815819

816820
/**
817821
* Return the OpenPGP packet encoding of the signature.
822+
*
818823
* @return OpenPGP packet encoding
819824
* @throws IOException
820825
*/
@@ -848,6 +853,7 @@ public byte[] getEncoded(boolean forTransfer)
848853
/**
849854
* Encode the signature to an OpenPGP packet stream.
850855
* This method does not strip out any trust packets.
856+
*
851857
* @param outStream packet stream
852858
* @throws IOException
853859
*/
@@ -901,6 +907,7 @@ public static boolean isCertification(int signatureType)
901907

902908
/**
903909
* Return true, if the cryptographic signature encoding of the two signatures match.
910+
*
904911
* @param sig1 first signature
905912
* @param sig2 second signature
906913
* @return true if both signatures contain the same cryptographic signature
@@ -916,6 +923,7 @@ public static boolean isSignatureEncodingEqual(PGPSignature sig1, PGPSignature s
916923
* (e.g. an embedded {@link #THIRD_PARTY_CONFIRMATION} signature), an implementation might want to
917924
* join an existing instance of a signature with an updated copy, e.g. retrieved from a key server.
918925
* This method merges both signature instances by joining unhashed subpackets.
926+
*
919927
* @param sig1 first signature
920928
* @param sig2 second signature
921929
* @return merged signature
@@ -924,7 +932,14 @@ public static boolean isSignatureEncodingEqual(PGPSignature sig1, PGPSignature s
924932
public static PGPSignature join(PGPSignature sig1, PGPSignature sig2)
925933
throws PGPException
926934
{
927-
if (!isSignatureEncodingEqual(sig1, sig2))
935+
if (sig1.getVersion() < SignaturePacket.VERSION_4)
936+
{
937+
// Version 2/3 signatures have no subpackets, so don't need to get merged.
938+
return sig1;
939+
}
940+
941+
if (sig1.getVersion() != sig2.getVersion() ||
942+
!isSignatureEncodingEqual(sig1, sig2))
928943
{
929944
throw new IllegalArgumentException("These are different signatures.");
930945
}

0 commit comments

Comments
 (0)