Generate GOST 34.10-2001 keypair and save it to so

2019-05-05 09:08发布

Currently I need to generate a keypair for GOST 34.10-2001 signature algorithm. It was pleasant to discover that bouncy castle provider has supported this algorithm, but I can not generate a keypair and save it to any keystore of any type. Currently I tried this command (this command works great if keyalg is DSA and sigalg is SHA1withDSA):

keytool -genkey -alias test1 -keyalg ECGOST3410 -keysize 512  -sigalg GOST3411withECGOST3410 \
-keypass test_1 -validity 1000 -storetype JKS -keystore test1.jks -storepass test_1 -v \
-provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "bcprov-jdk16-1.46.jar"

But I've got an error:

keytool error: java.lang.IllegalArgumentException: unknown key size.
java.lang.IllegalArgumentException: unknown key size.
        at sun.security.x509.CertAndKeyGen.generate(CertAndKeyGen.java:134)
        at sun.security.tools.KeyTool.doGenKeyPair(KeyTool.java:1156)
        at sun.security.tools.KeyTool.doCommands(KeyTool.java:786)
        at sun.security.tools.KeyTool.run(KeyTool.java:172)
        at sun.security.tools.KeyTool.main(KeyTool.java:166)

Exactly the same error I can see when I try to manipulate keysize or remove keysize option from the command. But there is some special case. When I set keysize to 256 I've got another error:

keytool error: java.lang.IllegalArgumentException: key size not configurable.
java.lang.IllegalArgumentException: key size not configurable.
        at sun.security.x509.CertAndKeyGen.generate(CertAndKeyGen.java:134)
        at sun.security.tools.KeyTool.doGenKeyPair(KeyTool.java:1156)
        at sun.security.tools.KeyTool.doCommands(KeyTool.java:786)
        at sun.security.tools.KeyTool.run(KeyTool.java:172)
        at sun.security.tools.KeyTool.main(KeyTool.java:166)

Currently I have no idea how to generate a keypair and how to save it to a keystore. Also I've got some java code that can generate a key pair for GOST 34.10-2001 algorithm:

Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECGOST3410", "BC");
kpg.initialize(new ECGenParameterSpec("GostR3410-2001-CryptoPro-A"));

KeyPair kp = kpg.generateKeyPair();

This code sample uses ECGenParameterSpec class to initialize a key pair generator, so may be I should provide it somehow to the keytool (-providerArg provider_arg or -Jjavaoption)?

P.S. I think that I should provide curve name as some parameter but I can not determine what parameter I should use.

1条回答
祖国的老花朵
2楼-- · 2019-05-05 09:23

You will not be able to use keytool and BC to create a keystore with GOST3410 keys.

sun.security.x509.CertAndKeyGen class used by the keytool does not provide an option to initialize the key generator with parameters, while BC GOST3410 key generator requires the initialization with ECParameterSpec.

You can create the keypair+certificate and place them into the keystore programmatically:

Security.addProvider( new org.bouncycastle.jce.provider.BouncyCastleProvider() );

KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance( "ECGOST3410", "BC" );
keyPairGenerator.initialize( new ECGenParameterSpec( "GostR3410-2001-CryptoPro-A" ) );
KeyPair keyPair = keyPairGenerator.generateKeyPair();

org.bouncycastle.asn1.x500.X500Name subject = new org.bouncycastle.asn1.x500.X500Name( "CN=Me" );
org.bouncycastle.asn1.x500.X500Name issuer = subject; // self-signed
BigInteger serial = BigInteger.ONE; // serial number for self-signed does not matter a lot
Date notBefore = new Date();
Date notAfter = new Date( notBefore.getTime() + TimeUnit.DAYS.toMillis( 365 ) );

org.bouncycastle.cert.X509v3CertificateBuilder certificateBuilder = new org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder(
        issuer, serial,
        notBefore, notAfter,
        subject, keyPair.getPublic()
);
org.bouncycastle.cert.X509CertificateHolder certificateHolder = certificateBuilder.build(
        new org.bouncycastle.operator.jcajce.JcaContentSignerBuilder( "GOST3411withECGOST3410" )
                .build( keyPair.getPrivate() )
);
org.bouncycastle.cert.jcajce.JcaX509CertificateConverter certificateConverter = new org.bouncycastle.cert.jcajce.JcaX509CertificateConverter();
X509Certificate certificate = certificateConverter.getCertificate( certificateHolder );

KeyStore keyStore = KeyStore.getInstance( "JKS" );
keyStore.load( null, null ); // initialize new keystore
keyStore.setEntry(
        "alias",
        new KeyStore.PrivateKeyEntry(
                keyPair.getPrivate(),
                new Certificate[] { certificate }
        ),
        new KeyStore.PasswordProtection( "entryPassword".toCharArray() )
);
keyStore.store( new FileOutputStream( "test.jks" ), "keystorePassword".toCharArray() );
查看更多
登录 后发表回答