mirrored from https://www.bouncycastle.org/repositories/bc-java
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Expand file tree
/
Copy pathOpenPGPPolicy.java
More file actions
331 lines (298 loc) · 12.1 KB
/
OpenPGPPolicy.java
File metadata and controls
331 lines (298 loc) · 12.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
package org.bouncycastle.openpgp.api;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import org.bouncycastle.bcpg.SignatureSubpacket;
import org.bouncycastle.bcpg.sig.NotationData;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.openpgp.PGPSignatureSubpacketVector;
/**
* Policy for OpenPGP algorithms and features.
*/
public interface OpenPGPPolicy
{
/**
* Return true, if the given {@link PGPPublicKey} is an acceptable signing key.
* Note: Although signing requires a secret key, we perform checks on the public part for consistency.
*
* @param key key
* @return true if acceptable signing key
*/
default boolean isAcceptableSigningKey(PGPPublicKey key)
{
return isAcceptablePublicKey(key);
}
/**
* Return true, if the given {@link PGPPublicKey} is an acceptable signature verification key.
* Note: The asymmetry between this and {@link #isAcceptableSigningKey(PGPPublicKey)} is useful
* to prevent creation of signatures using a legacy key, while still allowing verification of
* signatures made using the same key.
*
* @param key key
* @return true if acceptable verification key
*/
default boolean isAcceptableVerificationKey(PGPPublicKey key)
{
return isAcceptablePublicKey(key);
}
/**
* Return true, if the given {@link PGPPublicKey} is acceptable for encrypting messages.
*
* @param key key
* @return true if acceptable encryption key
*/
default boolean isAcceptableEncryptionKey(PGPPublicKey key)
{
return isAcceptablePublicKey(key);
}
/**
* Return true, if the given {@link PGPPublicKey} is acceptable for decrypting messages.
* Note: Although decryption requires a secret key, we perform checks on the public part for consistency.
* The asymmetry between this and {@link #isAcceptableEncryptionKey(PGPPublicKey)} is useful
* to prevent creation of new encrypted messages using a legacy key, while still allowing decryption
* of existing messages using the same key.
*
* @param key key
* @return true if acceptable decryption key
*/
default boolean isAcceptableDecryptionKey(PGPPublicKey key)
{
return isAcceptablePublicKey(key);
}
/**
* Return true, if the given {@link PGPPublicKey} is acceptable.
*
* @param key key
* @return true if acceptable key
*/
default boolean isAcceptablePublicKey(PGPPublicKey key)
{
return isAcceptablePublicKeyStrength(key.getAlgorithm(), key.getBitStrength());
}
/**
* Return true, if the given {@link PGPSignature} is acceptable (uses acceptable hash algorithm,
* does not contain unknown critical notations or subpackets).
* Note: A signature being acceptable does NOT mean that it is correct or valid.
*
* @param signature signature
* @return true if acceptable
*/
default boolean isAcceptableSignature(PGPSignature signature)
{
return hasAcceptableSignatureHashAlgorithm(signature) &&
hasNoCriticalUnknownNotations(signature) &&
hasNoCriticalUnknownSubpackets(signature);
}
/**
* Return true, if the given {@link PGPSignature} was made using an acceptable signature hash algorithm.
*
* @param signature signature
* @return true if hash algorithm is acceptable
*/
default boolean hasAcceptableSignatureHashAlgorithm(PGPSignature signature)
{
switch (signature.getSignatureType())
{
case PGPSignature.DEFAULT_CERTIFICATION:
case PGPSignature.NO_CERTIFICATION:
case PGPSignature.CASUAL_CERTIFICATION:
case PGPSignature.POSITIVE_CERTIFICATION:
case PGPSignature.DIRECT_KEY:
case PGPSignature.SUBKEY_BINDING:
case PGPSignature.PRIMARYKEY_BINDING:
return hasAcceptableCertificationSignatureHashAlgorithm(signature);
case PGPSignature.CERTIFICATION_REVOCATION:
case PGPSignature.KEY_REVOCATION:
case PGPSignature.SUBKEY_REVOCATION:
return hasAcceptableRevocationSignatureHashAlgorithm(signature);
case PGPSignature.BINARY_DOCUMENT:
case PGPSignature.CANONICAL_TEXT_DOCUMENT:
default:
return hasAcceptableDocumentSignatureHashAlgorithm(signature);
}
}
/**
* Return true, if the {@link PGPSignature} uses an acceptable data/document signature hash algorithm.
*
* @param signature data / document signature
* @return true if hash algorithm is acceptable
*/
default boolean hasAcceptableDocumentSignatureHashAlgorithm(PGPSignature signature)
{
return isAcceptableDocumentSignatureHashAlgorithm(signature.getHashAlgorithm(), signature.getCreationTime());
}
/**
* Return true, if the {@link PGPSignature} uses an acceptable revocation signature hash algorithm.
*
* @param signature revocation signature
* @return true if hash algorithm is acceptable
*/
default boolean hasAcceptableRevocationSignatureHashAlgorithm(PGPSignature signature)
{
return isAcceptableRevocationSignatureHashAlgorithm(signature.getHashAlgorithm(), signature.getCreationTime());
}
/**
* Return true, if the {@link PGPSignature} uses an acceptable certification signature hash algorithm.
*
* @param signature certification signature
* @return true if hash algorithm is acceptable
*/
default boolean hasAcceptableCertificationSignatureHashAlgorithm(PGPSignature signature)
{
return isAcceptableCertificationSignatureHashAlgorithm(signature.getHashAlgorithm(), signature.getCreationTime());
}
/**
* Return true, if the hashed subpacket area of the signature does NOT contain unknown critical notations.
* @param signature signature
* @return true if signature is free from unknown critical notations
*/
default boolean hasNoCriticalUnknownNotations(PGPSignature signature)
{
PGPSignatureSubpacketVector hashedSubpackets = signature.getHashedSubPackets();
if (hashedSubpackets == null)
{
return true;
}
OpenPGPNotationRegistry registry = getNotationRegistry();
NotationData[] notations = hashedSubpackets.getNotationDataOccurrences();
for (NotationData notation : notations)
{
if (notation.isCritical() && !registry.isNotationKnown(notation.getNotationName()))
{
return false;
}
}
return true;
}
/**
* Return true, if the hashed subpacket area of the signature does NOT contain unknown critical subpackets.
* @param signature signature
* @return true if signature is free from unknown critical subpackets
*/
default boolean hasNoCriticalUnknownSubpackets(PGPSignature signature)
{
PGPSignatureSubpacketVector hashedSubpackets = signature.getHashedSubPackets();
if (hashedSubpackets == null)
{
return true;
}
for (SignatureSubpacket subpacket : hashedSubpackets.toArray())
{
if (subpacket.isCritical() &&
// only consider subpackets which are not recognized by SignatureSubpacketInputStream
subpacket.getClass().equals(SignatureSubpacket.class))
{
if (!isKnownSignatureSubpacket(subpacket.getType()))
{
return false;
}
}
}
return true;
}
/**
* Return true, if the given signature subpacket ID is known by the implementation.
* Note: This method is only called for subpackets not recognized by
* {@link org.bouncycastle.bcpg.SignatureSubpacketInputStream}.
*
* @param signatureSubpacketTag signature subpacket ID
* @return true if subpacket tag is known
*/
default boolean isKnownSignatureSubpacket(int signatureSubpacketTag)
{
// Overwrite this, allowing custom critical signature subpackets
return false;
}
/**
* Return true, if the given hash algorithm is - at signature creation time - an acceptable document signature
* hash algorithm.
*
* @param hashAlgorithmId hash algorithm ID
* @param signatureCreationTime optional signature creation time
* @return true if hash algorithm is acceptable at creation time
*/
boolean isAcceptableDocumentSignatureHashAlgorithm(int hashAlgorithmId, Date signatureCreationTime);
/**
* Return true, if the given hash algorithm is - at signature creation time - an acceptable revocation signature
* hash algorithm.
*
* @param hashAlgorithmId hash algorithm ID
* @param signatureCreationTime optional signature creation time
* @return true if hash algorithm is acceptable at creation time
*/
boolean isAcceptableRevocationSignatureHashAlgorithm(int hashAlgorithmId, Date signatureCreationTime);
/**
* Return true, if the given hash algorithm is - at signature creation time - an acceptable certification signature
* hash algorithm.
*
* @param hashAlgorithmId hash algorithm ID
* @param signatureCreationTime optional signature creation time
* @return true if hash algorithm is acceptable at creation time
*/
boolean isAcceptableCertificationSignatureHashAlgorithm(int hashAlgorithmId, Date signatureCreationTime);
/**
* Return the default certification signature hash algorithm ID.
* This is used as fallback, if negotiation of a commonly supported hash algorithm fails.
*
* @return default certification signature hash algorithm ID
*/
int getDefaultCertificationSignatureHashAlgorithm();
/**
* Return the default document signature hash algorithm ID.
* This is used as fallback, if negotiation of a commonly supported hash algorithm fails.
*
* @return default document signature hash algorithm ID
*/
int getDefaultDocumentSignatureHashAlgorithm();
/**
* Return true, if the given symmetric-key algorithm is acceptable.
*
* @param symmetricKeyAlgorithmId symmetric-key algorithm
* @return true if symmetric-key algorithm is acceptable
*/
boolean isAcceptableSymmetricKeyAlgorithm(int symmetricKeyAlgorithmId);
/**
* Return the default symmetric-key algorithm, which is used as a fallback if symmetric encryption algorithm
* negotiation fails.
*
* @return default symmetric-key algorithm
*/
int getDefaultSymmetricKeyAlgorithm();
/**
* Return true, if the given bitStrength is acceptable for the given public key algorithm ID.
*
* @param publicKeyAlgorithmId ID of a public key algorithm
* @param bitStrength key bit strength
* @return true if strength is acceptable
*/
boolean isAcceptablePublicKeyStrength(int publicKeyAlgorithmId, int bitStrength);
/**
* Return the policies {@link OpenPGPNotationRegistry} containing known notation names.
*
* @return notation registry
*/
OpenPGPNotationRegistry getNotationRegistry();
/**
* The {@link OpenPGPNotationRegistry} can be used to register known notations, such that signatures containing
* notation instances of the same name, which are marked as critical do not invalidate the signature.
*/
class OpenPGPNotationRegistry
{
private final Set<String> knownNotations = new HashSet<String>();
public boolean isNotationKnown(String notationName)
{
return knownNotations.contains(notationName);
}
public void addKnownNotation(String notationName)
{
this.knownNotations.add(notationName);
}
}
/**
* The {@link OpenPGPCertificate.ComponentSignatureEvaluator} delegate defines, how component signatures on
* {@link OpenPGPCertificate OpenPGPCertificates} are being evaluated.
* @return delegate for component signature evaluation
*/
OpenPGPCertificate.ComponentSignatureEvaluator getComponentSignatureEffectivenessEvaluator();
}