22
33import java .io .IOException ;
44import java .util .ArrayList ;
5+ import java .util .Arrays ;
56import java .util .Date ;
67import java .util .List ;
78
3839 */
3940public class PGPSignatureSubpacketGenerator
4041{
41- List packets = new ArrayList ();
42+ List < SignatureSubpacket > packets = new ArrayList < SignatureSubpacket > ();
4243
4344 /**
4445 * Base constructor, creates an empty generator.
@@ -56,10 +57,7 @@ public PGPSignatureSubpacketGenerator(PGPSignatureSubpacketVector sigSubV)
5657 {
5758 if (sigSubV != null )
5859 {
59- for (int i = 0 ; i != sigSubV .packets .length ; i ++)
60- {
61- packets .add (sigSubV .packets [i ]);
62- }
60+ packets .addAll (Arrays .asList (sigSubV .packets ));
6361 }
6462 }
6563
@@ -78,6 +76,18 @@ public void setRevocable(boolean isCritical, boolean isRevocable)
7876 packets .add (new Revocable (isCritical , isRevocable ));
7977 }
8078
79+ /**
80+ * Specify, whether the signature should be marked as exportable.
81+ * If this subpacket is missing, the signature is treated as being exportable.
82+ * The subpacket is marked as critical, as is required (for non-exportable signatures) by the spec.
83+ *
84+ * @param isExportable true if the signature should be exportable, false otherwise.
85+ */
86+ public void setExportable (boolean isExportable )
87+ {
88+ setExportable (true , isExportable );
89+ }
90+
8191 /**
8292 * Specify, whether or not the signature should be marked as exportable.
8393 * If this subpacket is missing, the signature is treated as being exportable.
@@ -119,6 +129,18 @@ public void setTrust(boolean isCritical, int depth, int trustAmount)
119129 packets .add (new TrustSignature (isCritical , depth , trustAmount ));
120130 }
121131
132+ /**
133+ * Set the number of seconds a key is valid for after the time of its creation. A
134+ * value of zero means the key never expires.
135+ * The subpacket will be marked as critical, as is recommended by the spec.
136+ *
137+ * @param seconds seconds from key creation to expiration
138+ */
139+ public void setKeyExpirationTime (long seconds )
140+ {
141+ setKeyExpirationTime (true , seconds );
142+ }
143+
122144 /**
123145 * Set the number of seconds a key is valid for after the time of its creation. A
124146 * value of zero means the key never expires.
@@ -131,6 +153,19 @@ public void setKeyExpirationTime(boolean isCritical, long seconds)
131153 packets .add (new KeyExpirationTime (isCritical , seconds ));
132154 }
133155
156+ /**
157+ * Set the number of seconds a signature is valid for after the time of its creation.
158+ * A value of zero means the signature never expires.
159+ * The subpacket will be marked as critical, as is recommended by the spec.
160+ * .
161+ *
162+ * @param seconds seconds from signature creation to expiration
163+ */
164+ public void setSignatureExpirationTime (long seconds )
165+ {
166+ setSignatureExpirationTime (true , seconds );
167+ }
168+
134169 /**
135170 * Set the number of seconds a signature is valid for after the time of its creation.
136171 * A value of zero means the signature never expires.
@@ -143,6 +178,20 @@ public void setSignatureExpirationTime(boolean isCritical, long seconds)
143178 packets .add (new SignatureExpirationTime (isCritical , seconds ));
144179 }
145180
181+ /**
182+ * Set the creation time for the signature.
183+ * The subpacket will be marked as critical, as is recommended by the spec.
184+ * <p>
185+ * Note: this overrides the generation of a creation time when the signature is
186+ * generated.
187+ *
188+ * @param date date
189+ */
190+ public void setSignatureCreationTime (Date date )
191+ {
192+ setSignatureCreationTime (true , date );
193+ }
194+
146195 /**
147196 * Set the creation time for the signature.
148197 * <p>
@@ -212,11 +261,10 @@ public void setPreferredAEADAlgorithms(boolean isCritical, int[] algorithms)
212261 /**
213262 * Specify the preferred OpenPGP AEAD ciphersuites of this key.
214263 *
215- * @see <a href="https://www.rfc-editor.org/rfc/rfc9580.html#name-preferred-aead-ciphersuites">
216- * RFC9580: Preferred AEAD Ciphersuites</a>
217- *
218264 * @param isCritical true, if this packet should be treated as critical, false otherwise.
219265 * @param algorithms array of algorithms in descending preference
266+ * @see <a href="https://www.rfc-editor.org/rfc/rfc9580.html#name-preferred-aead-ciphersuites">
267+ * RFC9580: Preferred AEAD Ciphersuites</a>
220268 */
221269 public void setPreferredAEADCiphersuites (boolean isCritical , PreferredAEADCiphersuites .Combination [] algorithms )
222270 {
@@ -226,10 +274,9 @@ public void setPreferredAEADCiphersuites(boolean isCritical, PreferredAEADCipher
226274 /**
227275 * Specify the preferred OpenPGP AEAD ciphersuites of this key.
228276 *
229- * @see <a href="https://www.rfc-editor.org/rfc/rfc9580.html#name-preferred-aead-ciphersuites">
230- * RFC9580: Preferred AEAD Ciphersuites</a>
231- *
232277 * @param builder builder to build the ciphersuites packet from
278+ * @see <a href="https://www.rfc-editor.org/rfc/rfc9580.html#name-preferred-aead-ciphersuites">
279+ * RFC9580: Preferred AEAD Ciphersuites</a>
233280 */
234281 public void setPreferredAEADCiphersuites (PreferredAEADCiphersuites .Builder builder )
235282 {
@@ -243,12 +290,11 @@ public void setPreferredAEADCiphersuites(PreferredAEADCiphersuites.Builder build
243290 * The LibrePGP spec states that this subpacket shall be ignored and the application shall instead assume
244291 * {@link org.bouncycastle.bcpg.AEADAlgorithmTags#OCB}.
245292 *
246- * @see <a href="https://www.ietf.org/archive/id/draft-koch-librepgp-01.html#name-preferred-encryption-modes">
247- * LibrePGP: Preferred Encryption Modes</a>
248- * @see org.bouncycastle.bcpg.AEADAlgorithmTags for possible algorithms
249- *
250293 * @param isCritical whether the packet is critical
251294 * @param algorithms list of algorithms
295+ * @see <a href="https://www.ietf.org/archive/id/draft-koch-librepgp-01.html#name-preferred-encryption-modes">
296+ * LibrePGP: Preferred Encryption Modes</a>
297+ * @see org.bouncycastle.bcpg.AEADAlgorithmTags for possible algorithms
252298 * @deprecated the use of this subpacket is deprecated in LibrePGP
253299 */
254300 @ Deprecated
@@ -262,7 +308,7 @@ public void setPreferredLibrePgpEncryptionModes(boolean isCritical, int[] algori
262308 * Note, that the key server might also be a http/ftp etc. URI pointing to the key itself.
263309 *
264310 * @param isCritical true if the subpacket should be treated as critical
265- * @param uri key server URI
311+ * @param uri key server URI
266312 */
267313 public void setPreferredKeyServer (boolean isCritical , String uri )
268314 {
@@ -274,6 +320,18 @@ public void addPolicyURI(boolean isCritical, String policyUri)
274320 packets .add (new PolicyURI (isCritical , policyUri ));
275321 }
276322
323+ /**
324+ * Set this keys key flags.
325+ * See {@link PGPKeyFlags}.
326+ * The subpacket will be marked as critical, as is recommended by the spec.
327+ *
328+ * @param flags flags
329+ */
330+ public void setKeyFlags (int flags )
331+ {
332+ setKeyFlags (true , flags );
333+ }
334+
277335 /**
278336 * Set this keys key flags.
279337 * See {@link PGPKeyFlags}.
@@ -515,6 +573,19 @@ public void setIntendedRecipientFingerprint(boolean isCritical, PGPPublicKey pub
515573 addIntendedRecipientFingerprint (isCritical , publicKey );
516574 }
517575
576+ /**
577+ * Adds a intended recipient fingerprint for an encrypted payload the signature is associated with.
578+ * The subpacket will be marked as critical, as is recommended by the spec.
579+ *
580+ * @param publicKey the public key the encrypted payload was encrypted against.
581+ */
582+ public void addIntendedRecipientFingerprint (PGPPublicKey publicKey )
583+ {
584+ // RFC9580 states, that the packet SHOULD be critical if generated in a v6 signature,
585+ // but it doesn't harm to default to critical for any signature version
586+ addIntendedRecipientFingerprint (true , publicKey );
587+ }
588+
518589 /**
519590 * Adds a intended recipient fingerprint for an encrypted payload the signature is associated with.
520591 *
@@ -549,6 +620,26 @@ public boolean removePacket(SignatureSubpacket packet)
549620 return packets .remove (packet );
550621 }
551622
623+ /**
624+ * Remove all {@link SignatureSubpacket} objects of the given subpacketType from the underlying subpacket vector.
625+ *
626+ * @param subpacketType type to remove
627+ * @return true if any packet was removed, false otherwise
628+ */
629+ public boolean removePacketsOfType (int subpacketType )
630+ {
631+ boolean remove = false ;
632+ for (int i = packets .size () - 1 ; i >= 0 ; i --)
633+ {
634+ if (packets .get (i ).getType () == subpacketType )
635+ {
636+ packets .remove (i );
637+ remove = true ;
638+ }
639+ }
640+ return remove ;
641+ }
642+
552643 /**
553644 * Return true if a particular subpacket type exists.
554645 *
@@ -595,7 +686,7 @@ public SignatureSubpacket[] getSubpackets(
595686 public PGPSignatureSubpacketVector generate ()
596687 {
597688 return new PGPSignatureSubpacketVector (
598- ( SignatureSubpacket []) packets .toArray (new SignatureSubpacket [packets . size () ]));
689+ packets .toArray (new SignatureSubpacket [0 ]));
599690 }
600691
601692 private boolean contains (int type )
@@ -610,6 +701,17 @@ private boolean contains(int type)
610701 return false ;
611702 }
612703
704+ /**
705+ * Adds a regular expression.
706+ * The subpacket is marked as critical, as is recommended by the spec.
707+ *
708+ * @param regularExpression the regular expression
709+ */
710+ public void addRegularExpression (String regularExpression )
711+ {
712+ addRegularExpression (true , regularExpression );
713+ }
714+
613715 /**
614716 * Adds a regular expression.
615717 *
0 commit comments