Skip to content

Commit

Permalink
[ADD]SM2私钥转PKCS8 DER
Browse files Browse the repository at this point in the history
  • Loading branch information
ZZMarquis committed Mar 13, 2019
1 parent cfc7906 commit b090d28
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 1 deletion.
98 changes: 98 additions & 0 deletions src/main/java/org/zz/gmhelper/cert/SM2PrivateKey.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package org.zz.gmhelper.cert;

import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Encoding;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.DERBitString;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.asn1.x9.X962Parameters;
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil;
import org.bouncycastle.jcajce.provider.config.ProviderConfiguration;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.zz.gmhelper.BCECUtil;

import java.io.IOException;
import java.security.spec.ECParameterSpec;

public class SM2PrivateKey extends BCECPrivateKey {
private transient DERBitString sm2PublicKey;
private boolean withCompression;

public SM2PrivateKey(BCECPrivateKey privateKey, BCECPublicKey publicKey) {
super(privateKey.getAlgorithm(), privateKey);
this.sm2PublicKey = getSM2PublicKeyDetails(new SM2PublicKey(publicKey.getAlgorithm(), publicKey));
this.withCompression = false;
}

@Override
public void setPointFormat(String style)
{
withCompression = !("UNCOMPRESSED".equalsIgnoreCase(style));
}

/**
* Return a PKCS8 representation of the key. The sequence returned
* represents a full PrivateKeyInfo object.
*
* @return a PKCS8 representation of the key.
*/
@Override
public byte[] getEncoded()
{
ECParameterSpec ecSpec = getParams();
ProviderConfiguration configuration = BouncyCastleProvider.CONFIGURATION;
ASN1Encodable params = SM2PublicKey.ID_SM2_PUBKEY_PARAM;

int orderBitLength;
if (ecSpec == null)
{
orderBitLength = ECUtil.getOrderBitLength(configuration, null, this.getS());
}
else
{
orderBitLength = ECUtil.getOrderBitLength(configuration, ecSpec.getOrder(), this.getS());
}

PrivateKeyInfo info;
org.bouncycastle.asn1.sec.ECPrivateKey keyStructure;

if (sm2PublicKey != null)
{
keyStructure = new org.bouncycastle.asn1.sec.ECPrivateKey(orderBitLength, this.getS(), sm2PublicKey, params);
}
else
{
keyStructure = new org.bouncycastle.asn1.sec.ECPrivateKey(orderBitLength, this.getS(), params);
}

try
{
info = new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params), keyStructure);

return info.getEncoded(ASN1Encoding.DER);
}
catch (IOException e)
{
return null;
}
}

private DERBitString getSM2PublicKeyDetails(SM2PublicKey pub)
{
try
{
SubjectPublicKeyInfo info = SubjectPublicKeyInfo.getInstance(ASN1Primitive.fromByteArray(pub.getEncoded()));

return info.getPublicKeyData();
}
catch (IOException e)
{ // should never happen
return null;
}
}
}
7 changes: 6 additions & 1 deletion src/main/java/org/zz/gmhelper/cert/SM2PublicKey.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@ public class SM2PublicKey extends BCECPublicKey {

private boolean withCompression;

public SM2PublicKey(String algorithm, BCECPublicKey key) throws NoSuchFieldException, IllegalAccessException {
public SM2PublicKey(BCECPublicKey key) {
super(key.getAlgorithm(), key);
this.withCompression = false;
}

public SM2PublicKey(String algorithm, BCECPublicKey key) {
super(algorithm, key);
this.withCompression = false;
}
Expand Down
38 changes: 38 additions & 0 deletions src/test/java/org/zz/gmhelper/cert/test/SM2PrivateKeyTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package org.zz.gmhelper.cert.test;

import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
import org.junit.Assert;
import org.junit.Test;
import org.zz.gmhelper.SM2Util;
import org.zz.gmhelper.cert.SM2PrivateKey;
import org.zz.gmhelper.cert.SM2PublicKey;

import java.security.InvalidAlgorithmParameterException;
import java.security.KeyPair;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;

public class SM2PrivateKeyTest {
@Test
public void testEncoded() throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, NoSuchProviderException {
KeyPair keyPair = SM2Util.generateKeyPair();
BCECPrivateKey privateKey = (BCECPrivateKey) keyPair.getPrivate();
BCECPublicKey publicKey = (BCECPublicKey) keyPair.getPublic();
SM2PublicKey sm2PublicKey = new SM2PublicKey(publicKey.getAlgorithm(), publicKey);
SM2PrivateKey sm2PrivateKey1 = new SM2PrivateKey(privateKey, publicKey);
SM2PrivateKey sm2PrivateKey2 = new SM2PrivateKey(privateKey, sm2PublicKey);
String nativePriDER = ByteUtils.toHexString(privateKey.getEncoded());
String sm2PriDER1 = ByteUtils.toHexString(sm2PrivateKey1.getEncoded());
String sm2PriDER2 = ByteUtils.toHexString(sm2PrivateKey2.getEncoded());
if (nativePriDER.equalsIgnoreCase(sm2PriDER1)) {
Assert.fail();
}
if (!sm2PriDER1.equalsIgnoreCase(sm2PriDER2)) {
Assert.fail();
}
System.out.println("Native EC Private Key DER:\n" + nativePriDER.toUpperCase());
System.out.println("SM2 EC Private Key DER:\n" + sm2PriDER1.toUpperCase());
}
}

0 comments on commit b090d28

Please sign in to comment.