Skip to content

Commit e1aec63

Browse files
committed
Merge branch 'main' of gitlab.cryptoworkshop.com:root/bc-java
2 parents 3e31062 + cb76e2e commit e1aec63

File tree

79 files changed

+17300
-319
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+17300
-319
lines changed

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

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,41 @@ public Builder addComment(String comment)
612612
return addHeader(COMMENT_HDR, comment);
613613
}
614614

615+
public Builder addEllipsizedComment(String comment)
616+
{
617+
int availableCommentCharsPerLine = 64 - (COMMENT_HDR.length() + 2); // ASCII armor width - header len
618+
comment = comment.trim();
619+
620+
if (comment.length() > availableCommentCharsPerLine)
621+
{
622+
comment = comment.substring(0, availableCommentCharsPerLine - 1) + '…';
623+
}
624+
addComment(comment);
625+
return this;
626+
}
627+
628+
public Builder addSplitMultilineComment(String comment)
629+
{
630+
int availableCommentCharsPerLine = 64 - (COMMENT_HDR.length() + 2); // ASCII armor width - header len
631+
632+
comment = comment.trim();
633+
for (String line : comment.split("\n"))
634+
{
635+
while (line.length() > availableCommentCharsPerLine)
636+
{
637+
// split comment into multiple lines
638+
addComment(comment.substring(0, availableCommentCharsPerLine));
639+
line = line.substring(availableCommentCharsPerLine).trim();
640+
}
641+
642+
if (!line.isEmpty())
643+
{
644+
addComment(line);
645+
}
646+
}
647+
return this;
648+
}
649+
615650
/**
616651
* Set and replace the given header value with a single-line header.
617652
* If the value is <pre>null</pre>, this method will remove the header entirely.

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ public static boolean isSigningAlgorithm(int publicKeyAlgorithm)
3232

3333
// /**
3434
// * Return true, if the public key algorithm that corresponds to the given ID is capable of encryption.
35-
// *
3635
// * @param publicKeyAlgorithm public key algorithm id
3736
// * @return true if algorithm can encrypt
3837
// */

pg/src/main/java/org/bouncycastle/bcpg/sig/PreferredAEADCiphersuites.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ public class PreferredAEADCiphersuites
3030
*/
3131
private static final Combination AES_128_OCB = new Combination(SymmetricKeyAlgorithmTags.AES_128, AEADAlgorithmTags.OCB);
3232

33+
public static PreferredAEADCiphersuites DEFAULT()
34+
{
35+
return new PreferredAEADCiphersuites(false, new Combination[]{AES_128_OCB});
36+
}
37+
3338
/**
3439
* Create a new PreferredAEADAlgorithms signature subpacket from raw data.
3540
*
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package org.bouncycastle.openpgp;
2+
3+
import org.bouncycastle.bcpg.SymmetricEncIntegrityPacket;
4+
5+
import java.io.FilterInputStream;
6+
import java.io.IOException;
7+
import java.io.InputStream;
8+
9+
/**
10+
* {@link InputStream} that performs verification of integrity protection upon {@link #close()}.
11+
*/
12+
public class IntegrityProtectedInputStream
13+
extends FilterInputStream
14+
{
15+
16+
private final PGPEncryptedData esk;
17+
18+
public IntegrityProtectedInputStream(InputStream in, PGPEncryptedData dataPacket)
19+
{
20+
super(in);
21+
this.esk = dataPacket;
22+
}
23+
24+
@Override
25+
public int read()
26+
throws IOException
27+
{
28+
int i = in.read();
29+
if (i == -1)
30+
{
31+
close();
32+
}
33+
return i;
34+
}
35+
36+
@Override
37+
public int read(byte[] b)
38+
throws IOException
39+
{
40+
int r = in.read(b);
41+
if (r == -1)
42+
{
43+
close();
44+
}
45+
return r;
46+
}
47+
48+
@Override
49+
public int read(byte[] b, int off, int len)
50+
throws IOException
51+
{
52+
int r = in.read(b, off, len);
53+
if (r == -1)
54+
{
55+
close();
56+
}
57+
return r;
58+
}
59+
60+
@Override
61+
public void close()
62+
throws IOException
63+
{
64+
super.close();
65+
if (esk.getEncData() instanceof SymmetricEncIntegrityPacket)
66+
{
67+
SymmetricEncIntegrityPacket seipd = (SymmetricEncIntegrityPacket) esk.getEncData();
68+
if (seipd.getVersion() == SymmetricEncIntegrityPacket.VERSION_1)
69+
{
70+
try
71+
{
72+
if (!esk.verify())
73+
{
74+
throw new PGPException("Malformed integrity protected data.");
75+
}
76+
}
77+
catch (PGPException e)
78+
{
79+
throw new IOException(e);
80+
}
81+
}
82+
}
83+
}
84+
}

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,11 @@ public boolean isIntegrityProtected()
175175
return (encData instanceof SymmetricEncIntegrityPacket);
176176
}
177177

178+
public InputStreamPacket getEncData()
179+
{
180+
return encData;
181+
}
182+
178183
/**
179184
* Checks whether the packet is protected using an AEAD algorithm.
180185
*

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ public class PGPEncryptedDataGenerator
8888
// If true, force generation of a session key, even if we only have a single password-based encryption method
8989
// and could therefore use the S2K output as session key directly.
9090
private boolean forceSessionKey = true;
91+
private SessionKeyExtractionCallback sessionKeyExtractionCallback = null;
9192

9293
/**
9394
* Base constructor.
@@ -140,6 +141,10 @@ public void addMethod(PGPKeyEncryptionMethodGenerator method)
140141
methods.add(method);
141142
}
142143

144+
public void setSessionKeyExtractionCallback(SessionKeyExtractionCallback callback)
145+
{
146+
this.sessionKeyExtractionCallback = callback;
147+
}
143148

144149
/**
145150
* Create an OutputStream based on the configured methods.
@@ -213,6 +218,11 @@ else if (directS2K)
213218
messageKey = sessionKey;
214219
}
215220

221+
if (sessionKeyExtractionCallback != null)
222+
{
223+
sessionKeyExtractionCallback.extractSessionKey(new PGPSessionKey(defAlgorithm, sessionKey));
224+
}
225+
216226
PGPDataEncryptor dataEncryptor = dataEncryptorBuilder.build(messageKey);
217227
digestCalc = dataEncryptor.getIntegrityCalculator();
218228
BCPGHeaderObject encOut;
@@ -441,4 +451,9 @@ public void close()
441451
this.finish();
442452
}
443453
}
454+
455+
public interface SessionKeyExtractionCallback
456+
{
457+
void extractSessionKey(PGPSessionKey sessionKey);
458+
}
444459
}

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

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import java.io.OutputStream;
66
import java.util.ArrayList;
77
import java.util.Date;
8+
import java.util.Iterator;
89
import java.util.List;
910

1011
import org.bouncycastle.asn1.ASN1EncodableVector;
@@ -23,6 +24,8 @@
2324
import org.bouncycastle.bcpg.TrustPacket;
2425
import org.bouncycastle.bcpg.sig.IssuerFingerprint;
2526
import org.bouncycastle.bcpg.sig.IssuerKeyID;
27+
import org.bouncycastle.bcpg.sig.RevocationReason;
28+
import org.bouncycastle.bcpg.sig.RevocationReasonTags;
2629
import org.bouncycastle.math.ec.rfc8032.Ed25519;
2730
import org.bouncycastle.math.ec.rfc8032.Ed448;
2831
import org.bouncycastle.openpgp.operator.PGPContentVerifier;
@@ -635,11 +638,30 @@ public long getKeyID()
635638
public List<KeyIdentifier> getKeyIdentifiers()
636639
{
637640
List<KeyIdentifier> identifiers = new ArrayList<KeyIdentifier>();
638-
identifiers.addAll(getHashedKeyIdentifiers());
639-
identifiers.addAll(getUnhashedKeyIdentifiers());
641+
if (getVersion() <= SignaturePacket.VERSION_3)
642+
{
643+
identifiers.add(new KeyIdentifier(getKeyID()));
644+
}
645+
else
646+
{
647+
identifiers.addAll(getHashedKeyIdentifiers());
648+
identifiers.addAll(getUnhashedKeyIdentifiers());
649+
}
640650
return identifiers;
641651
}
642652

653+
public boolean hasKeyIdentifier(KeyIdentifier identifier)
654+
{
655+
for (Iterator it = getKeyIdentifiers().iterator(); it.hasNext(); )
656+
{
657+
if (((KeyIdentifier)it.next()).matches(identifier))
658+
{
659+
return true;
660+
}
661+
}
662+
return false;
663+
}
664+
643665
/**
644666
* Return a list of all {@link KeyIdentifier KeyIdentifiers} that could be derived from
645667
* any {@link IssuerFingerprint} or {@link IssuerKeyID} subpackets of the hashed signature
@@ -905,6 +927,46 @@ public static boolean isCertification(int signatureType)
905927
|| PGPSignature.POSITIVE_CERTIFICATION == signatureType;
906928
}
907929

930+
public static boolean isRevocation(int signatureType)
931+
{
932+
return PGPSignature.KEY_REVOCATION == signatureType
933+
|| PGPSignature.CERTIFICATION_REVOCATION == signatureType
934+
|| PGPSignature.SUBKEY_REVOCATION == signatureType;
935+
}
936+
937+
public boolean isHardRevocation()
938+
{
939+
if (!isRevocation(getSignatureType()))
940+
{
941+
return false; // no revocation
942+
}
943+
944+
if (!hasSubpackets())
945+
{
946+
return true; // consider missing subpackets (and therefore missing reason) as hard revocation
947+
}
948+
949+
// only consider reasons from the hashed packet area
950+
RevocationReason reason = getHashedSubPackets() != null ?
951+
getHashedSubPackets().getRevocationReason() : null;
952+
if (reason == null)
953+
{
954+
return true; // missing reason packet is hard
955+
}
956+
957+
byte code = reason.getRevocationReason();
958+
if (code >= 100 && code <= 110)
959+
{
960+
// private / experimental reasons are considered hard
961+
return true;
962+
}
963+
964+
// Reason is not from the set of known soft reasons
965+
return code != RevocationReasonTags.KEY_SUPERSEDED &&
966+
code != RevocationReasonTags.KEY_RETIRED &&
967+
code != RevocationReasonTags.USER_NO_LONGER_VALID;
968+
}
969+
908970
/**
909971
* Return true, if the cryptographic signature encoding of the two signatures match.
910972
*
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package org.bouncycastle.openpgp;
2+
3+
public class PGPSignatureException
4+
extends PGPException
5+
{
6+
public PGPSignatureException(String message)
7+
{
8+
super(message);
9+
}
10+
11+
public PGPSignatureException(String message, Exception cause)
12+
{
13+
super(message, cause);
14+
}
15+
}

0 commit comments

Comments
 (0)