Skip to content

Commit 8756876

Browse files
committed
Merge branch 'rfc9708-cms-hss-lms' into 'main'
Rfc9708 See merge request root/bc-java!72
2 parents c30fd65 + 9e25ed9 commit 8756876

File tree

9 files changed

+372
-3
lines changed

9 files changed

+372
-3
lines changed

core/src/main/java/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@ public interface PKCSObjectIdentifiers
278278
* id-alg-hss-lms-hashsig OBJECT IDENTIFIER ::= { iso(1)
279279
* member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
280280
* smime(16) alg(3) 17 }
281+
* 1.2.840.113549.1.9.16.3.17
281282
*/
282283
public static final ASN1ObjectIdentifier id_alg_hss_lms_hashsig = smime_alg.branch("17");
283284

core/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,8 @@ public static AsymmetricKeyParameter createKey(SubjectPublicKeyInfo keyInfo, Obj
165165
SubjectPublicKeyInfoConverter converter = (SubjectPublicKeyInfoConverter)converters.get(algID.getAlgorithm());
166166
if (null == converter)
167167
{
168-
throw new IOException("algorithm identifier in public key not recognised: " + algID.getAlgorithm());
168+
return org.bouncycastle.pqc.crypto.util.PublicKeyFactory.createKey(keyInfo, defaultParams);
169+
//throw new IOException("algorithm identifier in public key not recognised: " + algID.getAlgorithm());
169170
}
170171

171172
return converter.getPublicKeyParameters(keyInfo, defaultParams);

core/src/main/java/org/bouncycastle/crypto/util/SubjectPublicKeyInfoFactory.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,17 @@
3535
import org.bouncycastle.crypto.params.X448PublicKeyParameters;
3636
import org.bouncycastle.internal.asn1.edec.EdECObjectIdentifiers;
3737
import org.bouncycastle.internal.asn1.rosstandart.RosstandartObjectIdentifiers;
38+
import org.bouncycastle.pqc.crypto.lms.Composer;
39+
import org.bouncycastle.pqc.crypto.lms.HSSPublicKeyParameters;
40+
import org.bouncycastle.pqc.crypto.lms.LMSPublicKeyParameters;
41+
import org.bouncycastle.util.Arrays;
3842

3943
/**
4044
* Factory to create ASN.1 subject public key info objects from lightweight public keys.
4145
*/
4246
public class SubjectPublicKeyInfoFactory
4347
{
48+
private static final byte tag_OctetString = (byte)0x04;
4449
private static Set cryptoProOids = new HashSet(5);
4550

4651
static
@@ -192,6 +197,20 @@ else if (publicKey instanceof Ed25519PublicKeyParameters)
192197

193198
return new SubjectPublicKeyInfo(new AlgorithmIdentifier(EdECObjectIdentifiers.id_Ed25519), key.getEncoded());
194199
}
200+
else if (publicKey instanceof HSSPublicKeyParameters)
201+
{
202+
HSSPublicKeyParameters params = (HSSPublicKeyParameters)publicKey;
203+
byte[] encoding = Composer.compose().u32str(params.getL()).bytes(params.getLMSPublicKey()).build();
204+
AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PKCSObjectIdentifiers.id_alg_hss_lms_hashsig);
205+
return new SubjectPublicKeyInfo(algorithmIdentifier, Arrays.concatenate(new byte[]{tag_OctetString, (byte)encoding.length}, encoding));
206+
}
207+
else if (publicKey instanceof LMSPublicKeyParameters)
208+
{
209+
LMSPublicKeyParameters params = (LMSPublicKeyParameters)publicKey;
210+
byte[] encoding = Composer.compose().u32str(1).bytes(params).build();
211+
AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PKCSObjectIdentifiers.id_alg_hss_lms_hashsig);
212+
return new SubjectPublicKeyInfo(algorithmIdentifier, Arrays.concatenate(new byte[]{tag_OctetString, (byte)encoding.length}, encoding));
213+
}
195214
else
196215
{
197216
throw new IOException("key parameters not recognized");

core/src/main/java/org/bouncycastle/internal/asn1/kisa/KISAObjectIdentifiers.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,7 @@ public interface KISAObjectIdentifiers
2828

2929
/** RFC 4010: SeedEncryptionAlgorithmInCMS; OID 1.2.840.113549.1.9.16.0.24 */
3030
static final ASN1ObjectIdentifier id_mod_cms_seed = new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.0.24");
31+
32+
/** RFC 9708 MTS-HashSig-2013; OID 1.2.840.113549.1.9.16.0.64 */
33+
static final ASN1ObjectIdentifier id_mod_mts_hashsig_2013 = new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.0.64");
3134
}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
package org.bouncycastle.operator.bc;
2+
3+
import java.io.ByteArrayOutputStream;
4+
5+
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
6+
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
7+
import org.bouncycastle.crypto.CipherParameters;
8+
import org.bouncycastle.crypto.CryptoException;
9+
import org.bouncycastle.crypto.DataLengthException;
10+
import org.bouncycastle.crypto.Signer;
11+
import org.bouncycastle.operator.OperatorCreationException;
12+
import org.bouncycastle.pqc.crypto.MessageSigner;
13+
import org.bouncycastle.pqc.crypto.lms.HSSPrivateKeyParameters;
14+
import org.bouncycastle.pqc.crypto.lms.HSSPublicKeyParameters;
15+
import org.bouncycastle.pqc.crypto.lms.HSSSigner;
16+
import org.bouncycastle.pqc.crypto.lms.LMSPrivateKeyParameters;
17+
import org.bouncycastle.pqc.crypto.lms.LMSPublicKeyParameters;
18+
import org.bouncycastle.pqc.crypto.lms.LMSSigner;
19+
20+
/**
21+
* Builder for creating content signers that use the HSS/LMS Hash-Based Signature Algorithm.
22+
*
23+
* <b>Reference:</b> Use of the HSS/LMS Hash-Based Signature Algorithm in the Cryptographic Message Syntax (CMS)
24+
* <a href="https://datatracker.ietf.org/doc/rfc9708/">RFC 9708</a>.
25+
*/
26+
public class BcHssLmsContentSignerBuilder
27+
extends BcContentSignerBuilder
28+
{
29+
private static final AlgorithmIdentifier sigAlgId = new AlgorithmIdentifier(PKCSObjectIdentifiers.id_alg_hss_lms_hashsig);
30+
31+
public BcHssLmsContentSignerBuilder()
32+
{
33+
super(sigAlgId, null);
34+
}
35+
36+
protected Signer createSigner(AlgorithmIdentifier sigAlgId, AlgorithmIdentifier digAlgId)
37+
throws OperatorCreationException
38+
{
39+
return new HssSigner();
40+
}
41+
42+
static class HssSigner
43+
implements Signer
44+
{
45+
private MessageSigner signer;
46+
private final ByteArrayOutputStream stream = new ByteArrayOutputStream();
47+
48+
public HssSigner()
49+
{
50+
}
51+
52+
@Override
53+
public void init(boolean forSigning, CipherParameters param)
54+
{
55+
if (param instanceof HSSPublicKeyParameters || param instanceof HSSPrivateKeyParameters)
56+
{
57+
signer = new HSSSigner();
58+
}
59+
else if (param instanceof LMSPublicKeyParameters || param instanceof LMSPrivateKeyParameters)
60+
{
61+
signer = new LMSSigner();
62+
}
63+
else
64+
{
65+
throw new IllegalArgumentException("Incorrect Key Parameters");
66+
}
67+
68+
signer.init(forSigning, param);
69+
}
70+
71+
@Override
72+
public void update(byte b)
73+
{
74+
stream.write(b);
75+
}
76+
77+
@Override
78+
public void update(byte[] in, int off, int len)
79+
{
80+
stream.write(in, off, len);
81+
}
82+
83+
@Override
84+
public byte[] generateSignature()
85+
throws CryptoException, DataLengthException
86+
{
87+
byte[] msg = stream.toByteArray();
88+
stream.reset();
89+
return signer.generateSignature(msg);
90+
}
91+
92+
@Override
93+
public boolean verifySignature(byte[] signature)
94+
{
95+
byte[] msg = stream.toByteArray();
96+
stream.reset();
97+
return signer.verifySignature(msg, signature);
98+
}
99+
100+
@Override
101+
public void reset()
102+
{
103+
stream.reset();
104+
}
105+
}
106+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package org.bouncycastle.operator.bc;
2+
3+
import java.io.IOException;
4+
5+
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
6+
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
7+
import org.bouncycastle.crypto.Signer;
8+
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
9+
import org.bouncycastle.crypto.util.PublicKeyFactory;
10+
import org.bouncycastle.operator.OperatorCreationException;
11+
12+
/**
13+
* Builder for creating content verifier providers that support the HSS/LMS Hash-Based Signature Algorithm.
14+
*
15+
* <b>Reference:</b> Use of the HSS/LMS Hash-Based Signature Algorithm in the Cryptographic Message Syntax (CMS)
16+
* <a href="https://datatracker.ietf.org/doc/rfc9708/">RFC 9708</a>.
17+
* </p>
18+
*/
19+
public class BcHssLmsContentVerifierProviderBuilder
20+
extends BcContentVerifierProviderBuilder
21+
{
22+
public BcHssLmsContentVerifierProviderBuilder()
23+
{
24+
}
25+
26+
protected Signer createSigner(AlgorithmIdentifier sigAlgId)
27+
throws OperatorCreationException
28+
{
29+
return new BcHssLmsContentSignerBuilder.HssSigner();
30+
}
31+
32+
protected AsymmetricKeyParameter extractKeyParameters(SubjectPublicKeyInfo publicKeyInfo)
33+
throws IOException
34+
{
35+
return PublicKeyFactory.createKey(publicKeyInfo);
36+
}
37+
}

0 commit comments

Comments
 (0)