1 package org.bouncycastle.pqc.crypto.util;
2 
3 import java.io.IOException;
4 
5 import org.bouncycastle.asn1.ASN1Set;
6 import org.bouncycastle.asn1.DEROctetString;
7 import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
8 import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
9 import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
10 import org.bouncycastle.pqc.asn1.PQCObjectIdentifiers;
11 import org.bouncycastle.pqc.asn1.SPHINCS256KeyParams;
12 import org.bouncycastle.pqc.crypto.newhope.NHPrivateKeyParameters;
13 import org.bouncycastle.pqc.crypto.qtesla.QTESLAPrivateKeyParameters;
14 import org.bouncycastle.pqc.crypto.sphincs.SPHINCSPrivateKeyParameters;
15 import org.bouncycastle.util.Pack;
16 
17 /**
18  * Factory to create ASN.1 private key info objects from lightweight private keys.
19  */
20 public class PrivateKeyInfoFactory
21 {
PrivateKeyInfoFactory()22     private PrivateKeyInfoFactory()
23     {
24 
25     }
26 
27     /**
28      * Create a PrivateKeyInfo representation of a private key.
29      *
30      * @param privateKey the key to be encoded into the info object.
31      * @return the appropriate PrivateKeyInfo
32      * @throws java.io.IOException on an error encoding the key
33      */
createPrivateKeyInfo(AsymmetricKeyParameter privateKey)34     public static PrivateKeyInfo createPrivateKeyInfo(AsymmetricKeyParameter privateKey) throws IOException
35     {
36         return createPrivateKeyInfo(privateKey, null);
37     }
38 
39     /**
40      * Create a PrivateKeyInfo representation of a private key with attributes.
41      *
42      * @param privateKey the key to be encoded into the info object.
43      * @param attributes the set of attributes to be included.
44      * @return the appropriate PrivateKeyInfo
45      * @throws java.io.IOException on an error encoding the key
46      */
createPrivateKeyInfo(AsymmetricKeyParameter privateKey, ASN1Set attributes)47     public static PrivateKeyInfo createPrivateKeyInfo(AsymmetricKeyParameter privateKey, ASN1Set attributes) throws IOException
48     {
49         if (privateKey instanceof QTESLAPrivateKeyParameters)
50         {
51             QTESLAPrivateKeyParameters keyParams = (QTESLAPrivateKeyParameters)privateKey;
52 
53             AlgorithmIdentifier algorithmIdentifier = Utils.qTeslaLookupAlgID(keyParams.getSecurityCategory());
54 
55             return new PrivateKeyInfo(algorithmIdentifier, new DEROctetString(keyParams.getSecret()), attributes);
56         }
57         else if (privateKey instanceof SPHINCSPrivateKeyParameters)
58         {
59             SPHINCSPrivateKeyParameters params = (SPHINCSPrivateKeyParameters)privateKey;
60             AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PQCObjectIdentifiers.sphincs256,
61                                     new SPHINCS256KeyParams(Utils.sphincs256LookupTreeAlgID(params.getTreeDigest())));
62 
63             return new PrivateKeyInfo(algorithmIdentifier, new DEROctetString(params.getKeyData()));
64         }
65         else if (privateKey instanceof NHPrivateKeyParameters)
66         {
67             NHPrivateKeyParameters params = (NHPrivateKeyParameters)privateKey;
68 
69             AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PQCObjectIdentifiers.newHope);
70 
71             short[] privateKeyData = params.getSecData();
72 
73             byte[] octets = new byte[privateKeyData.length * 2];
74             for (int i = 0; i != privateKeyData.length; i++)
75             {
76                 Pack.shortToLittleEndian(privateKeyData[i], octets, i * 2);
77             }
78 
79             return new PrivateKeyInfo(algorithmIdentifier, new DEROctetString(octets));
80         }
81         else
82         {
83             throw new IOException("key parameters not recognized");
84         }
85     }
86 }
87