Skip to content

Commit c64e774

Browse files
author
gefeili
committed
#1750 Implement PreferredKeyServer signature subpacket
1 parent 394e709 commit c64e774

File tree

4 files changed

+69
-0
lines changed

4 files changed

+69
-0
lines changed

pg/src/main/java/org/bouncycastle/bcpg/SignatureSubpacketInputStream.java

+3
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import org.bouncycastle.bcpg.sig.PolicyURI;
1717
import org.bouncycastle.bcpg.sig.PreferredAEADCiphersuites;
1818
import org.bouncycastle.bcpg.sig.PreferredAlgorithms;
19+
import org.bouncycastle.bcpg.sig.PreferredKeyServer;
1920
import org.bouncycastle.bcpg.sig.PrimaryUserID;
2021
import org.bouncycastle.bcpg.sig.RegularExpression;
2122
import org.bouncycastle.bcpg.sig.Revocable;
@@ -152,6 +153,8 @@ else if (flags[StreamUtil.flag_partial])
152153
return new PreferredAlgorithms(type, isCritical, isLongLength, data);
153154
case PREFERRED_AEAD_ALGORITHMS:
154155
return new PreferredAEADCiphersuites(isCritical, isLongLength, data);
156+
case PREFERRED_KEY_SERV:
157+
return new PreferredKeyServer(isCritical, isLongLength, data);
155158
case KEY_FLAGS:
156159
return new KeyFlags(isCritical, isLongLength, data);
157160
case POLICY_URL:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package org.bouncycastle.bcpg.sig;
2+
3+
import org.bouncycastle.bcpg.SignatureSubpacket;
4+
import org.bouncycastle.bcpg.SignatureSubpacketTags;
5+
import org.bouncycastle.util.Arrays;
6+
import org.bouncycastle.util.Strings;
7+
8+
/**
9+
* Signature Subpacket containing the URI of the users preferred key server.
10+
* This is a URI of a key server that the key holder prefers be used for updates.
11+
* Note that keys with multiple User IDs can have a preferred key server for each User ID.
12+
* Note also that since this is a URI, the key server can actually be a copy of the key
13+
* retrieved by ftp, http, finger, etc.
14+
*
15+
* @see <a href="https://datatracker.ietf.org/doc/html/rfc4880#section-5.2.3.18">
16+
* RFC4880 - Preferred Key Server</a>
17+
* @see <a href="https://www.rfc-editor.org/rfc/rfc9580.html#name-preferred-key-server">
18+
* RFC9580 - Preferred Key Server</a>
19+
*/
20+
public class PreferredKeyServer
21+
extends SignatureSubpacket
22+
{
23+
public PreferredKeyServer(boolean critical, boolean isLongLength, byte[] data)
24+
{
25+
super(SignatureSubpacketTags.PREFERRED_KEY_SERV, critical, isLongLength, data);
26+
}
27+
28+
public PreferredKeyServer(boolean critical, String uri)
29+
{
30+
this(critical, false, Strings.toUTF8ByteArray(uri));
31+
}
32+
33+
/**
34+
* Return the URI of the users preferred key server.
35+
* @return key server uri
36+
*/
37+
public String getURI()
38+
{
39+
return Strings.fromUTF8ByteArray(data);
40+
}
41+
42+
public byte[] getRawURI()
43+
{
44+
return Arrays.clone(data);
45+
}
46+
}

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

+13
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import org.bouncycastle.bcpg.sig.NotationData;
1919
import org.bouncycastle.bcpg.sig.PolicyURI;
2020
import org.bouncycastle.bcpg.sig.PreferredAlgorithms;
21+
import org.bouncycastle.bcpg.sig.PreferredKeyServer;
2122
import org.bouncycastle.bcpg.sig.PrimaryUserID;
2223
import org.bouncycastle.bcpg.sig.RegularExpression;
2324
import org.bouncycastle.bcpg.sig.Revocable;
@@ -202,6 +203,18 @@ public void setPreferredAEADAlgorithms(boolean isCritical, int[] algorithms)
202203
algorithms));
203204
}
204205

206+
/**
207+
* Specify the preferred key server for the signed user-id / key.
208+
* Note, that the key server might also be a http/ftp etc. URI pointing to the key itself.
209+
*
210+
* @param isCritical true if the subpacket should be treated as critical
211+
* @param uri key server URI
212+
*/
213+
public void setPreferredKeyServer(boolean isCritical, String uri)
214+
{
215+
packets.add(new PreferredKeyServer(isCritical, uri));
216+
}
217+
205218
public void addPolicyURI(boolean isCritical, String policyUri)
206219
{
207220
packets.add(new PolicyURI(isCritical, policyUri));

pg/src/test/java/org/bouncycastle/openpgp/test/OpenPGPTest.java

+7
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,11 @@
1919
import org.bouncycastle.bcpg.CompressionAlgorithmTags;
2020
import org.bouncycastle.bcpg.HashAlgorithmTags;
2121
import org.bouncycastle.bcpg.PublicKeyAlgorithmTags;
22+
import org.bouncycastle.bcpg.SignatureSubpacketTags;
2223
import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags;
2324
import org.bouncycastle.bcpg.sig.Features;
2425
import org.bouncycastle.bcpg.sig.KeyFlags;
26+
import org.bouncycastle.bcpg.sig.PreferredKeyServer;
2527
import org.bouncycastle.crypto.CryptoServicesRegistrar;
2628
import org.bouncycastle.jce.provider.BouncyCastleProvider;
2729
import org.bouncycastle.jce.spec.ECNamedCurveGenParameterSpec;
@@ -458,6 +460,7 @@ public void operation()
458460

459461
PGPSignatureSubpacketGenerator hashed = new PGPSignatureSubpacketGenerator();
460462
hashed.addNotationData(false, true, "[email protected]", "hashedNotation");
463+
hashed.setPreferredKeyServer(false, "www.testuri.com");
461464
PGPSignatureSubpacketGenerator unhashed = new PGPSignatureSubpacketGenerator();
462465

463466
PGPContentSignerBuilder signerBuilder = new BcPGPContentSignerBuilder(PublicKeyAlgorithmTags.ECDSA, HashAlgorithmTags.SHA512);
@@ -472,6 +475,10 @@ public void operation()
472475
PGPSignature signature = (PGPSignature)signatures.next();
473476
isTrue(!signatures.hasNext());
474477

478+
PreferredKeyServer pks = (PreferredKeyServer)signature.getHashedSubPackets().getSubpackets(SignatureSubpacketTags.PREFERRED_KEY_SERV)[0];
479+
isTrue(pks.getURI().equals("www.testuri.com"));
480+
isTrue(pks.getRawURI().length == 15);
481+
475482
verifier = new PGPSignatureVerifierBuilder(new JcaPGPContentVerifierBuilderProvider().setProvider("BC"), publicKey).buildDirectKeyVerifier(signature, publicKey);
476483
isTrue(verifier.isVerified());
477484
isTrue(verifier.getSignatureType() == PGPSignature.DIRECT_KEY);

0 commit comments

Comments
 (0)