Skip to content

Commit 15c5a96

Browse files
gefeilidghgit
gefeili
authored andcommitted
Add some ObjectIdentifier. Pass the test for HSS signer.
1 parent 508dbf9 commit 15c5a96

File tree

8 files changed

+213
-22
lines changed

8 files changed

+213
-22
lines changed

Diff for: core/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java

+2-1
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);

Diff for: core/src/main/java/org/bouncycastle/crypto/util/SubjectPublicKeyInfoFactory.java

+12
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@
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.util.Arrays;
3841

3942
/**
4043
* Factory to create ASN.1 subject public key info objects from lightweight public keys.
@@ -192,6 +195,15 @@ else if (publicKey instanceof Ed25519PublicKeyParameters)
192195

193196
return new SubjectPublicKeyInfo(new AlgorithmIdentifier(EdECObjectIdentifiers.id_Ed25519), key.getEncoded());
194197
}
198+
else if (publicKey instanceof HSSPublicKeyParameters)
199+
{
200+
HSSPublicKeyParameters params = (HSSPublicKeyParameters)publicKey;
201+
final byte tag_OctetString = (byte) 0x04;
202+
byte[] encoding = Composer.compose().u32str(params.getL()).bytes(params.getLMSPublicKey()).build();
203+
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+
}
195207
else
196208
{
197209
throw new IOException("key parameters not recognized");

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

+3
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
}
Original file line numberDiff line numberDiff line change
@@ -1,81 +1,96 @@
11
package org.bouncycastle.operator.bc;
22

3+
import java.io.ByteArrayOutputStream;
4+
import java.io.IOException;
5+
6+
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
37
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
48
import org.bouncycastle.crypto.CipherParameters;
59
import org.bouncycastle.crypto.CryptoException;
610
import org.bouncycastle.crypto.DataLengthException;
7-
import org.bouncycastle.crypto.Digest;
811
import org.bouncycastle.crypto.Signer;
912
import org.bouncycastle.operator.OperatorCreationException;
1013
import org.bouncycastle.pqc.crypto.MessageSigner;
14+
import org.bouncycastle.pqc.crypto.lms.HSSPrivateKeyParameters;
15+
import org.bouncycastle.pqc.crypto.lms.HSSPublicKeyParameters;
1116
import org.bouncycastle.pqc.crypto.lms.HSSSigner;
17+
import org.bouncycastle.util.Arrays;
1218

1319
public class BcHssLmsContentSignerBuilder
1420
extends BcContentSignerBuilder
1521
{
16-
public BcHssLmsContentSignerBuilder(AlgorithmIdentifier sigAlgId, AlgorithmIdentifier digAlgId)
22+
private static final AlgorithmIdentifier sigAlgId = new AlgorithmIdentifier(PKCSObjectIdentifiers.id_alg_hss_lms_hashsig);
23+
24+
public BcHssLmsContentSignerBuilder()
1725
{
18-
super(sigAlgId, digAlgId);
26+
super(sigAlgId, null);
1927
}
2028

2129
protected Signer createSigner(AlgorithmIdentifier sigAlgId, AlgorithmIdentifier digAlgId)
2230
throws OperatorCreationException
2331
{
24-
Digest dig = digestProvider.get(digAlgId);
25-
26-
return new HssSigner(dig);
32+
return new HssSigner();
2733
}
2834

29-
private static class HssSigner
35+
static class HssSigner
3036
implements Signer
3137
{
3238
private final MessageSigner hss = new HSSSigner();
33-
private final Digest digest;
39+
private final ByteArrayOutputStream stream = new ByteArrayOutputStream();
40+
private HSSPublicKeyParameters publicKeyParameters;
41+
static final byte tag_OctetString = 0x04;
3442

35-
public HssSigner(Digest digest)
43+
public HssSigner()
3644
{
37-
this.digest = digest;
3845
}
3946

4047
@Override
4148
public void init(boolean forSigning, CipherParameters param)
4249
{
4350
hss.init(forSigning, param);
51+
if (forSigning)
52+
{
53+
publicKeyParameters = ((HSSPrivateKeyParameters)param).getPublicKey();
54+
}
55+
else
56+
{
57+
publicKeyParameters = (HSSPublicKeyParameters)param;
58+
}
4459
}
4560

4661
@Override
4762
public void update(byte b)
4863
{
49-
digest.update(b);
64+
stream.write(b);
5065
}
5166

5267
@Override
5368
public void update(byte[] in, int off, int len)
5469
{
55-
digest.update(in, off, len);
70+
stream.write(in, off, len);
5671
}
5772

5873
@Override
5974
public byte[] generateSignature()
6075
throws CryptoException, DataLengthException
6176
{
62-
byte[] hash = new byte[digest.getDigestSize()];
63-
digest.doFinal(hash, 0);
64-
return hss.generateSignature(hash);
77+
byte[] msg = stream.toByteArray();
78+
stream.reset();
79+
return hss.generateSignature(msg);
6580
}
6681

6782
@Override
6883
public boolean verifySignature(byte[] signature)
6984
{
70-
byte[] hash = new byte[digest.getDigestSize()];
71-
digest.doFinal(hash, 0);
72-
return hss.verifySignature(hash, signature);
85+
byte[] msg = stream.toByteArray();
86+
stream.reset();
87+
return hss.verifySignature(msg, signature);
7388
}
7489

7590
@Override
7691
public void reset()
7792
{
78-
digest.reset();
93+
stream.reset();
7994
}
8095
}
8196
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
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+
public class BcHssLmsContentVerifierProviderBuilder
13+
extends BcContentVerifierProviderBuilder
14+
{
15+
public BcHssLmsContentVerifierProviderBuilder()
16+
{
17+
}
18+
19+
protected Signer createSigner(AlgorithmIdentifier sigAlgId)
20+
throws OperatorCreationException
21+
{
22+
return new BcHssLmsContentSignerBuilder.HssSigner();
23+
}
24+
25+
protected AsymmetricKeyParameter extractKeyParameters(SubjectPublicKeyInfo publicKeyInfo)
26+
throws IOException
27+
{
28+
return PublicKeyFactory.createKey(publicKeyInfo);
29+
}
30+
}

Diff for: pkix/src/test/java/org/bouncycastle/cms/test/PQCSignedDataTest.java

+107-2
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,17 @@
22

33
import java.io.ByteArrayInputStream;
44
import java.io.IOException;
5+
import java.math.BigInteger;
56
import java.security.KeyPair;
67
import java.security.MessageDigest;
8+
import java.security.SecureRandom;
79
import java.security.Security;
810
import java.security.cert.CertificateException;
11+
import java.security.cert.CertificateFactory;
912
import java.security.cert.X509Certificate;
1013
import java.util.ArrayList;
1114
import java.util.Collection;
15+
import java.util.Date;
1216
import java.util.HashSet;
1317
import java.util.Iterator;
1418
import java.util.List;
@@ -27,8 +31,14 @@
2731
import org.bouncycastle.asn1.cms.SignerInfo;
2832
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
2933
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
34+
import org.bouncycastle.asn1.x500.X500NameBuilder;
35+
import org.bouncycastle.asn1.x500.style.RFC4519Style;
3036
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
3137
import org.bouncycastle.cert.X509CertificateHolder;
38+
import org.bouncycastle.cert.X509v1CertificateBuilder;
39+
import org.bouncycastle.cert.X509v3CertificateBuilder;
40+
import org.bouncycastle.cert.bc.BcX509v1CertificateBuilder;
41+
import org.bouncycastle.cert.bc.BcX509v3CertificateBuilder;
3242
import org.bouncycastle.cert.jcajce.JcaCertStore;
3343
import org.bouncycastle.cms.CMSException;
3444
import org.bouncycastle.cms.CMSProcessableByteArray;
@@ -40,11 +50,31 @@
4050
import org.bouncycastle.cms.SignerInformationStore;
4151
import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder;
4252
import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder;
53+
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
54+
import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
55+
import org.bouncycastle.crypto.generators.DSAKeyPairGenerator;
56+
import org.bouncycastle.crypto.generators.DSAParametersGenerator;
57+
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
58+
import org.bouncycastle.crypto.params.DSAKeyGenerationParameters;
59+
import org.bouncycastle.crypto.params.DSAParameters;
60+
import org.bouncycastle.crypto.util.PublicKeyFactory;
4361
import org.bouncycastle.jce.provider.BouncyCastleProvider;
62+
import org.bouncycastle.operator.ContentSigner;
4463
import org.bouncycastle.operator.DigestCalculatorProvider;
4564
import org.bouncycastle.operator.OperatorCreationException;
65+
import org.bouncycastle.operator.bc.BcDSAContentSignerBuilder;
66+
import org.bouncycastle.operator.bc.BcDSAContentVerifierProviderBuilder;
67+
import org.bouncycastle.operator.bc.BcHssLmsContentSignerBuilder;
68+
import org.bouncycastle.operator.bc.BcHssLmsContentVerifierProviderBuilder;
4669
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
4770
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
71+
import org.bouncycastle.pqc.crypto.lms.HSSKeyGenerationParameters;
72+
import org.bouncycastle.pqc.crypto.lms.HSSKeyPairGenerator;
73+
import org.bouncycastle.pqc.crypto.lms.LMOtsParameters;
74+
import org.bouncycastle.pqc.crypto.lms.LMSKeyGenerationParameters;
75+
import org.bouncycastle.pqc.crypto.lms.LMSKeyPairGenerator;
76+
import org.bouncycastle.pqc.crypto.lms.LMSParameters;
77+
import org.bouncycastle.pqc.crypto.lms.LMSigParameters;
4878
import org.bouncycastle.pqc.jcajce.provider.BouncyCastlePQCProvider;
4979
import org.bouncycastle.util.Store;
5080

@@ -104,7 +134,7 @@ public static void main(String args[])
104134
throws Exception
105135
{
106136
init();
107-
137+
//checkCreationHssLms();
108138
junit.textui.TestRunner.run(PQCSignedDataTest.class);
109139
}
110140

@@ -321,7 +351,7 @@ public void testLmsEncapsulated()
321351

322352
assertTrue(digAlgIds.contains(new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha256)));
323353
assertTrue(digAlgIds.size() == 1);
324-
354+
325355
certs = s.getCertificates();
326356

327357
SignerInformationStore signers = s.getSignerInfos();
@@ -352,6 +382,81 @@ public void testLmsEncapsulated()
352382
}
353383
}
354384

385+
public void testCheckCreationHssLms()
386+
throws Exception
387+
{
388+
//
389+
// set up the keys
390+
//
391+
AsymmetricKeyParameter privKey;
392+
AsymmetricKeyParameter pubKey;
393+
394+
AsymmetricCipherKeyPairGenerator kpg = new HSSKeyPairGenerator();
395+
396+
kpg.init(new HSSKeyGenerationParameters(
397+
new LMSParameters[]{new LMSParameters(LMSigParameters.lms_sha256_n32_h5, LMOtsParameters.sha256_n32_w4)}, new SecureRandom()));
398+
399+
AsymmetricCipherKeyPair pair = kpg.generateKeyPair();
400+
401+
privKey = (AsymmetricKeyParameter)pair.getPrivate();
402+
pubKey = (AsymmetricKeyParameter)pair.getPublic();
403+
404+
//
405+
// distinguished name table.
406+
//
407+
X500NameBuilder builder = new X500NameBuilder(RFC4519Style.INSTANCE);
408+
409+
builder.addRDN(RFC4519Style.c, "AU");
410+
builder.addRDN(RFC4519Style.o, "The Legion of the Bouncy Castle");
411+
builder.addRDN(RFC4519Style.l, "Melbourne");
412+
builder.addRDN(RFC4519Style.st, "Victoria");
413+
builder.addRDN(PKCSObjectIdentifiers.pkcs_9_at_emailAddress, "feedback-crypto@bouncycastle.org");
414+
415+
//
416+
// extensions
417+
//
418+
419+
//
420+
// create the certificate - version 3
421+
//
422+
423+
424+
ContentSigner sigGen = new BcHssLmsContentSignerBuilder().build(privKey);
425+
X509v3CertificateBuilder certGen = new BcX509v3CertificateBuilder(builder.build(), BigInteger.valueOf(1), new Date(System.currentTimeMillis() - 50000), new Date(System.currentTimeMillis() + 50000), builder.build(), pubKey);
426+
427+
428+
X509CertificateHolder cert = certGen.build(sigGen);
429+
430+
assertTrue(cert.isValidOn(new Date()));
431+
432+
assertTrue(cert.isSignatureValid(new BcHssLmsContentVerifierProviderBuilder().build(pubKey)));
433+
434+
435+
//
436+
// create the certificate - version 1
437+
//
438+
439+
sigGen = new BcHssLmsContentSignerBuilder().build(privKey);
440+
X509v1CertificateBuilder certGen1 = new BcX509v1CertificateBuilder(builder.build(), BigInteger.valueOf(1), new Date(System.currentTimeMillis() - 50000), new Date(System.currentTimeMillis() + 50000), builder.build(), pubKey);
441+
442+
cert = certGen1.build(sigGen);
443+
444+
assertTrue(cert.isValidOn(new Date()));
445+
446+
assertTrue(cert.isSignatureValid(new BcHssLmsContentVerifierProviderBuilder().build(pubKey)));
447+
448+
AsymmetricKeyParameter certPubKey = PublicKeyFactory.createKey(cert.getSubjectPublicKeyInfo());
449+
450+
assertTrue(cert.isSignatureValid(new BcHssLmsContentVerifierProviderBuilder().build(certPubKey)));
451+
452+
ByteArrayInputStream bIn = new ByteArrayInputStream(cert.getEncoded());
453+
CertificateFactory fact = CertificateFactory.getInstance("X.509");
454+
455+
X509Certificate x509cert = (X509Certificate)fact.generateCertificate(bIn);
456+
457+
//System.out.println(cert);
458+
}
459+
355460
public void testTryLmsSettings()
356461
throws Exception
357462
{

Diff for: util/src/main/java/org/bouncycastle/asn1/kisa/KISAObjectIdentifiers.java

+3
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
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package org.bouncycastle.asn1.mod;
2+
3+
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
4+
5+
public interface ModObjectIdentifiers
6+
{
7+
//TODO: add more from RFC 6268, RFC 5911
8+
9+
// id_mod OBJECT IDENTIFIER ::= { iso(1) identified_organization(3)
10+
// dod(6) internet(1) security(5) mechanisms(5) pkix(7) mod(0) }
11+
ASN1ObjectIdentifier id_mod = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.0");
12+
13+
/**
14+
* PUBLIC-KEY, SIGNATURE-ALGORITHM, SMIME-CAPS
15+
* FROM AlgorithmInformation-2009 -- RFC 5911 [CMSASN1]
16+
* { iso(1) identified-organization(3) dod(6) internet(1)
17+
* security(5) mechanisms(5) pkix(7) id-mod(0)
18+
* id-mod-algorithmInformation-02(58) } ;
19+
* 1.3.6.1.5.5.7.0.58
20+
*/
21+
ASN1ObjectIdentifier id_mod_algorithmInformation_02 = id_mod.branch("58");
22+
}

0 commit comments

Comments
 (0)