Tencent / TencentKonaSMSuite

Tencent Kona SM Suite contains a set of Java security providers, which support algorithms SM2, SM3 and SM4, and protocols TLCP/GMSSL, TLS 1.3 (with RFC 8998) and TLS 1.2.
Other
370 stars 73 forks source link

如何生成测试用的证书 #336

Closed xudong-1990 closed 1 year ago

xudong-1990 commented 1 year ago

首先,非常感谢Kona国密套件以及Tencent团队对该国密套件的支持! 我目前在对OAuth2授权服务进行国密改造,授权服务端使用的是kona-demo中使用的签给localhost的证书,而授权服务器测试时就是通过localhost访问,所以访问正常。 但是测试用的客户端无法用localhost访问(这与授权服务器相关,无法都用localhost访问),所以在对客户端进行国密改造的时候,我需要生成新的keystore和truststore,我尝试通过GMSSL实验室申请双证书,但是启动的时候会报错,我想了解以下,我如何自己生成客户端的keystore和truststore?

xudong-1990 commented 1 year ago

通过GMSSL实验室,我生成了以下文件: 无标题 需要按照kona-pkix/README.md文件中的方法,使用keyStoreTool将证书存到keystore中

java -cp <...> KeyStoreTool \
  -type PKCS12 \
  -alias trust1,trust2 \
  -certs /path/to/cas.pem \
  -store /path/to/store.p12 \
  -storePasswd changeit

请问我怎样配置才能使用TKSS的KeyStoreTool工具?

xudong-1990 commented 1 year ago

TKSS不支持HmacPBESHA256 算法吗?

C:\Users\Administrator\Desktop\kona\sm2.client.com>java -cp kona-pkix-1.0.9.jar;libs/* com.tencent.kona.pkix.tool.KeyStoreTool -type PKCS12 -alias gmsslrca,gmssloca -certs cas.pem -store truststore.p12 -storePasswd 12345678 Exception in thread "main" java.io.IOException: calculateMac failed: java.security.NoSuchAlgorithmException: Algorithm HmacPBESHA256 not available at com.tencent.kona.sun.security.pkcs12.PKCS12KeyStore.calculateMac(PKCS12KeyStore.java:1537) at com.tencent.kona.sun.security.pkcs12.PKCS12KeyStore.engineStore(PKCS12KeyStore.java:1277) at java.security.KeyStore.store(KeyStore.java:1377) at com.tencent.kona.pkix.tool.KeyStoreTool.saveStore(KeyStoreTool.java:206) at com.tencent.kona.pkix.tool.KeyStoreTool.createTrustStore(KeyStoreTool.java:166) at com.tencent.kona.pkix.tool.KeyStoreTool.main(KeyStoreTool.java:140) Caused by: java.security.NoSuchAlgorithmException: Algorithm HmacPBESHA256 not available at javax.crypto.Mac.getInstance(Mac.java:181) at com.tencent.kona.crypto.CryptoInsts.getMac(CryptoInsts.java:165) at com.tencent.kona.sun.security.pkcs12.PKCS12KeyStore.calculateMac(PKCS12KeyStore.java:1518) ... 5 more

xudong-1990 commented 1 year ago

TKSS不支持HmacPBESHA256 算法吗?

C:\Users\Administrator\Desktop\kona\sm2.client.com>java -cp kona-pkix-1.0.9.jar;libs/* com.tencent.kona.pkix.tool.KeyStoreTool -type PKCS12 -alias gmsslrca,gmssloca -certs cas.pem -store truststore.p12 -storePasswd 12345678
Exception in thread "main" java.io.IOException: calculateMac failed: java.security.NoSuchAlgorithmException: Algorithm HmacPBESHA256 not available
        at com.tencent.kona.sun.security.pkcs12.PKCS12KeyStore.calculateMac(PKCS12KeyStore.java:1537)
        at com.tencent.kona.sun.security.pkcs12.PKCS12KeyStore.engineStore(PKCS12KeyStore.java:1277)
        at java.security.KeyStore.store(KeyStore.java:1377)
        at com.tencent.kona.pkix.tool.KeyStoreTool.saveStore(KeyStoreTool.java:206)
        at com.tencent.kona.pkix.tool.KeyStoreTool.createTrustStore(KeyStoreTool.java:166)
        at com.tencent.kona.pkix.tool.KeyStoreTool.main(KeyStoreTool.java:140)
Caused by: java.security.NoSuchAlgorithmException: Algorithm HmacPBESHA256 not available
        at javax.crypto.Mac.getInstance(Mac.java:181)
        at com.tencent.kona.crypto.CryptoInsts.getMac(CryptoInsts.java:165)
        at com.tencent.kona.sun.security.pkcs12.PKCS12KeyStore.calculateMac(PKCS12KeyStore.java:1518)
        ... 5 more

使用KeyStoreTool的测试类中的方法,可以生成keystore和trust store,但是在服务启动的时候报错:

org.springframework.context.ApplicationContextException: Failed to start bean 'webServerStartStop'
    at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:181) ~[spring-context-6.0.9.jar:6.0.9]
    at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:356) ~[spring-context-6.0.9.jar:6.0.9]
    at java.base/java.lang.Iterable.forEach(Iterable.java:75) ~[na:na]
    at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:155) ~[spring-context-6.0.9.jar:6.0.9]
    at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:123) ~[spring-context-6.0.9.jar:6.0.9]
    at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:958) ~[spring-context-6.0.9.jar:6.0.9]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:611) ~[spring-context-6.0.9.jar:6.0.9]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.1.0.jar:3.1.0]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:733) ~[spring-boot-3.1.0.jar:3.1.0]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:435) ~[spring-boot-3.1.0.jar:3.1.0]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:311) ~[spring-boot-3.1.0.jar:3.1.0]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1305) ~[spring-boot-3.1.0.jar:3.1.0]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1294) ~[spring-boot-3.1.0.jar:3.1.0]
    at cn.fisec.client.KonaClientApplication.main(KonaClientApplication.java:53) ~[classes/:na]
Caused by: org.springframework.boot.web.server.WebServerException: Unable to start embedded Jetty server
    at org.springframework.boot.web.embedded.jetty.JettyWebServer.start(JettyWebServer.java:180) ~[spring-boot-3.1.0.jar:3.1.0]
    at org.springframework.boot.web.servlet.context.WebServerStartStopLifecycle.start(WebServerStartStopLifecycle.java:44) ~[spring-boot-3.1.0.jar:3.1.0]
    at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:178) ~[spring-context-6.0.9.jar:6.0.9]
    ... 13 common frames omitted
Caused by: java.security.UnrecoverableKeyException: Get Key failed: Given final block not properly padded. Such issues can arise if a bad key is used during decryption.
    at com.tencent.kona.sun.security.pkcs12.PKCS12KeyStore.engineGetKey(PKCS12KeyStore.java:479) ~[kona-pkix-1.0.9.jar:na]
    at java.base/java.security.KeyStore.getKey(KeyStore.java:1050) ~[na:na]
    at com.tencent.kona.sun.security.ssl.SunX509KeyManagerImpl.<init>(SunX509KeyManagerImpl.java:140) ~[kona-ssl-1.0.9.jar:na]
    at com.tencent.kona.sun.security.ssl.KeyManagerFactoryImpl$SunX509.engineInit(KeyManagerFactoryImpl.java:64) ~[kona-ssl-1.0.9.jar:na]
    at java.base/javax.net.ssl.KeyManagerFactory.init(KeyManagerFactory.java:275) ~[na:na]
    at org.eclipse.jetty.util.ssl.SslContextFactory.getKeyManagers(SslContextFactory.java:1167) ~[jetty-util-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.util.ssl.SslContextFactory$Server.getKeyManagers(SslContextFactory.java:2289) ~[jetty-util-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.util.ssl.SslContextFactory.load(SslContextFactory.java:342) ~[jetty-util-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.util.ssl.SslContextFactory.doStart(SslContextFactory.java:213) ~[jetty-util-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:93) ~[jetty-util-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:171) ~[jetty-util-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:121) ~[jetty-util-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.server.SslConnectionFactory.doStart(SslConnectionFactory.java:112) ~[jetty-server-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:93) ~[jetty-util-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:171) ~[jetty-util-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:121) ~[jetty-util-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.server.AbstractConnector.doStart(AbstractConnector.java:367) ~[jetty-server-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.server.AbstractNetworkConnector.doStart(AbstractNetworkConnector.java:75) ~[jetty-server-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.server.ServerConnector.doStart(ServerConnector.java:228) ~[jetty-server-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:93) ~[jetty-util-11.0.15.jar:11.0.15]
    at org.springframework.boot.web.embedded.jetty.JettyWebServer.start(JettyWebServer.java:161) ~[spring-boot-3.1.0.jar:3.1.0]
    ... 15 common frames omitted
Caused by: javax.crypto.BadPaddingException: Given final block not properly padded. Such issues can arise if a bad key is used during decryption.
    at java.base/com.sun.crypto.provider.CipherCore.unpad(CipherCore.java:859) ~[na:na]
    at java.base/com.sun.crypto.provider.CipherCore.fillOutputBuffer(CipherCore.java:939) ~[na:na]
    at java.base/com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:735) ~[na:na]
    at java.base/com.sun.crypto.provider.PBES2Core.engineDoFinal(PBES2Core.java:325) ~[na:na]
    at java.base/javax.crypto.Cipher.doFinal(Cipher.java:2205) ~[na:na]
    at com.tencent.kona.sun.security.pkcs12.PKCS12KeyStore.lambda$engineGetKey$0(PKCS12KeyStore.java:402) ~[kona-pkix-1.0.9.jar:na]
    at com.tencent.kona.sun.security.pkcs12.PKCS12KeyStore$RetryWithZero.run(PKCS12KeyStore.java:286) ~[kona-pkix-1.0.9.jar:na]
    at com.tencent.kona.sun.security.pkcs12.PKCS12KeyStore.engineGetKey(PKCS12KeyStore.java:393) ~[kona-pkix-1.0.9.jar:na]
    ... 35 common frames omitted

考虑到证书是由GMSSL实验室生成的,是否存在兼容性问题?接下来尝试用TKSS生成密钥····

johnshajiang commented 1 year ago

感觉上面异常应该是与PKCS12密钥库有关,还没有涉及到私钥和证书本身。 能否提供你测试时使用的密钥库文件,以方便我进行测试?

xudong-1990 commented 1 year ago

我在ubuntu下安装了babassl后用TencentKonaSMSuite-master\kona-pkix\src\test\resources\gen_tlcp_certs.sh脚本生成了以下这些文件(部分是合并来的,比如cas)

ca.ext       ee.ext       tlcp-client-enc.crt   tlcp-client.crt     tlcp-intca.crt       tlcp-server-enc.key   tlcp-server.key
cas.pem      tlcp-ca.crt  tlcp-client-enc.key   tlcp-client.key     tlcp-intca.key       tlcp-server-sign.crt  tlcp-sign-ee-lo.crt
ee-enc.ext   tlcp-ca.key  tlcp-client-sign.crt  tlcp-enc-ee-lo.crt  tlcp-intca.pem       tlcp-server-sign.key  tlcp-sign-ee-lo.key
ee-sign.ext  tlcp-ca.pem  tlcp-client-sign.key  tlcp-enc-ee-lo.key  tlcp-server-enc.crt  tlcp-server.crt

p12zip.zip 附件是用keystoreTool生成的P12文件,密码都是 12345678

另外:下面是我生成p12的方法,是按照测试类改的

private void createKeyStore() throws Exception {
        String type = "PKCS12";
        String storePathString = "path/to/keystore-server.p12";
        String storePasswd = "12345678";

        String signAlias = "sign";
        String signKeyPath = "path/to/tlcp-server-sign.key";
        String signCertChainPath = "path/to/tlcp-server-sign.crt";

        String encAlias = "enc";
        String encKeyPath = "path/to/tlcp-server-enc.key";
        String encCertChainPath = "path/to/tlcp-server-enc.crt";

        String[] signArgs = new String[] {
                "-type", type,
                "-alias", signAlias,
                "-keyAlgo", "EC",
                "-key", signKeyPath, // This private key is not encrypted
                "-keyPasswd", "12345678",
                "-certs", signCertChainPath,
                "-store", storePathString,//storePath.toString(),
                "-storePasswd", storePasswd };
        KeyStoreTool.main(signArgs);

        String[] encArgs = new String[] {
                "-type", type,
                "-alias", encAlias,
                "-keyAlgo", "EC",
                "-key", encKeyPath, // This private key is encrypted
                "-keyPasswd", "12345678",
                "-certs", encCertChainPath,
                "-store", storePathString,//storePath.toString(),
                "-storePasswd", storePasswd };
        KeyStoreTool.main(encArgs);

        KeyStore trustStore = PKIXInsts.getKeyStore(type);
        try (InputStream in = new FileInputStream(storePathString)) {
            trustStore.load(in, storePasswd.toCharArray());
        }
        trustStore.getCertificate(signAlias);
        trustStore.getCertificate(encAlias);

    }
xudong-1990 commented 1 year ago

目前项目已经跑通,应该是在设置客户端的keystore的时候,错误使用了服务端的,具体的方案接下来会重新生成客户端和服务端的证书以及keystore进行验证,如有结果会跟进记录

johnshajiang commented 1 year ago

@xudong-1990 由于本周休假,无法及时地分析问题 ;-(

很高兴你已经解决了当前的问题。 若有新的问题,欢迎随时沟通。

xudong-1990 commented 1 year ago

@xudong-1990 由于本周休假,无法及时地分析问题 ;-(

很高兴你已经解决了当前的问题。 若有新的问题,欢迎随时沟通。

感谢!是您之前的回答启发了我。 总结一下密钥生成过程:

步骤一:安装TongSuo Openssl

简介:

铜锁/Tongsuo是一个提供现代密码学算法和安全通信协议的开源基础密码库,为存储、网络、密钥管理、隐私计算等诸多业务场景提供底层的密码学基础能力,实现数据在传输、使用、存储等过程中的私密性、完整性和可认证性,为数据生命周期中的隐私和安全提供保护能力。

铜锁获得了国家密码管理局商用密码检测中心颁发的商用密码产品认证证书,助力用户在国密改造、密评、等保等过程中,更加严谨地满足我国商用密码技术合规的要求。

开源地址:[Tongsuo-Project/Tongsuo: 铜锁/Tongsuo is a Modern Cryptographic Primitives and Protocols Library (github.com)](https://github.com/Tongsuo-Project/Tongsuo)

源码编译

详细教程请参考[源码编译 (yuque.com)](https://www.yuque.com/tsdoc/ts/rp7ul8a4ttav8ql9)

  1. 源码准备:

从GitHub下载源码压缩包,[Release BabaSSL-8.3.2 · Tongsuo-Project/Tongsuo (github.com)](https://github.com/Tongsuo-Project/Tongsuo/releases/tag/8.3.2)

或者使用git clone

# clone master 分支代码
git clone git@github.com:Tongsuo-Project/Tongsuo.git
  1. 编译安装
# 配置选项
./config --prefix=/opt/tongsuo -Wl,-rpath,/opt/tongsuo/lib enable-ec_elgamal  enable-ntls

# 查看 config 结果
perl configdata.pm --dump

# 编译
make -j

# 安装
make install
  1. 为新安装的openssl配置环境变量

以Ubuntu22.04为例

进入~目录下,vim .bashrc打开配置文件,在最后添加下面的代码:

#Tongsuo
export TONGSUO_HOME=/opt/tongsuo
export PATH=${TONGSUO_HOME}/bin:$PATH

保存并退出后,执行source .bashrc使配置生效,之后即可使用tongsuo的openssl命令;

注意:

如果系统中已经安装了openssl,本教程需要手动卸载openssl,然后再安装tongsuo,铜锁是openssl的一个分支,支持原有openssl的功能。

步骤二:修改密钥生成脚本

找到项目kona-ssl/src/test/resources/gen_tlcp_certs.sh文件,可根据需要进行修改,建议修改位置如下:

  1. 文件保存目录
#!/usr/bin/env bash

TLCP_DIR="my_tlcp_dir" # 将这里改成自定义的目录名称
if [ ! -d ${TLCP_DIR} ]; then
  echo "mkdir tlcp_certs"
  mkdir ${TLCP_DIR}
fi
cd ${TLCP_DIR}
  1. 修改openssl命令

可以修改CA和Intermediate CA中"/CN="部分,这里也可以不修改。

##### CA
$OPENSSL genpkey -algorithm ec -pkeyopt ec_paramgen_curve:SM2 -pkeyopt ec_param_enc:named_curve -out tlcp-ca.key
$OPENSSL req -new -key tlcp-ca.key -subj "/CN=tlcp-ca" -sm3 -out tlcp-ca.csr
$OPENSSL x509 -extfile ca.ext -req -CAcreateserial -days 3650 -in tlcp-ca.csr -sm3 \
    -signkey tlcp-ca.key -out tlcp-ca.crt.tmp
$OPENSSL x509 -text -in tlcp-ca.crt.tmp > tlcp-ca.crt

##### Intermediate CA
$OPENSSL genpkey -algorithm ec -pkeyopt ec_paramgen_curve:SM2 -pkeyopt ec_param_enc:named_curve -out tlcp-intca.key
$OPENSSL req -new -key tlcp-intca.key -subj "/CN=tlcp-intca" -sm3 -out tlcp-intca.csr
$OPENSSL x509 -extfile ca.ext -req -CAcreateserial -days 3650 -in tlcp-intca.csr -sm3 \
    -CA tlcp-ca.crt -CAkey tlcp-ca.key -out tlcp-intca.crt.tmp
$OPENSSL x509 -text -in tlcp-intca.crt.tmp > tlcp-intca.crt
  1. 修改客户端和服务端的签名证书和加密证书的脚本
# 本教程只能支持SM2的双证,即keystore中国包含签名证书和加密证书,这里建议分开生成两张证书,以Server端为例

##### Sign EE (Server)
$OPENSSL genpkey -algorithm ec -pkeyopt ec_paramgen_curve:SM2 -pkeyopt ec_param_enc:named_curve -out tlcp-server-sign.key
$OPENSSL req -new -key tlcp-server-sign.key -subj "/CN=server.com" -sm3 -out tlcp-server-sign.csr
$OPENSSL x509 -extfile ee-sign.ext -req -CAcreateserial -days 3650 -in tlcp-server-sign.csr -sm3 \
    -CA tlcp-intca.crt -CAkey tlcp-intca.key -out tlcp-server-sign.crt.tmp
$OPENSSL x509 -text -in tlcp-server-sign.crt.tmp > tlcp-server-sign.crt

##### Enc EE (Server)
$OPENSSL genpkey -algorithm ec -pkeyopt ec_paramgen_curve:SM2 -pkeyopt ec_param_enc:named_curve -out tlcp-server-enc.key
$OPENSSL req -new -key tlcp-server-enc.key -subj "/CN=server.com" -sm3 -out tlcp-server-enc.csr
$OPENSSL x509 -extfile ee-enc.ext -req -CAcreateserial -days 3650 -in tlcp-server-enc.csr -sm3 \
    -CA tlcp-intca.crt -CAkey tlcp-intca.key -out tlcp-server-enc.crt.tmp
$OPENSSL x509 -text -in tlcp-server-enc.crt.tmp > tlcp-server-enc.crt
  1. 将修改后的脚本拷贝到Linux中,执行bash ./gen_tlcp_certs.sh命令

​ 执行脚本后会在配置好的文件夹下生成私钥和证书。

ca.ext       tlcp-ca.crt          tlcp-client-sign.crt  tlcp-enc-ee-lo.crt  tlcp-server-enc.crt   tlcp-server.crt
ee-enc.ext   tlcp-ca.key          tlcp-client-sign.key  tlcp-enc-ee-lo.key  tlcp-server-enc.key   tlcp-server.key
ee-sign.ext  tlcp-client-enc.crt  tlcp-client.crt       tlcp-intca.crt      tlcp-server-sign.crt  tlcp-sign-ee-lo.crt
ee.ext       tlcp-client-enc.key  tlcp-client.key       tlcp-intca.key      tlcp-server-sign.key  tlcp-sign-ee-lo.key

步骤三:合并中间CA和根CA为一个文件

在步骤二中,会分别生成tlcp-ca.crttlcp-intca.crt两个CA证书,其中tlcp-ca.crt是根CA,tlcp-intca.crt是颁发客户端和服务端的中间CA证书。在步骤四中,生成TrustStore的输入项要求的是包含所有CA证书的pem格式的证书文件,所以这一步需要将以上两张CA证书分别转成PEM格式,并将两个pem格式的CA证书合并为同一个。

# 将crt证书文件转成pem证书文件
 openssl x509 -in tlcp-ca.crt -out tlcp-ca.pem -outform PEM
 openssl x509 -in tlcp-intca.crt -out tlcp-intca.pem -outform PEM
# 查看.crt文件具体信息
openssl x509 -in tlcp-ca.crt -noout -text
openssl x509 -in tlcp-intca.crt -noout -text
# 可以通过命令查看pem证书文件内容
 cat tlcp-intca.pem
 cat tlcp-ca.pem
# 合并pem文件,注意:这里建议中间CA在前,根CA在后,这与步骤四对应
 cat tlcp-intca.pem tlcp-ca.pem > cas.pem
# 查看合并文件
 cat cas.pem

步骤四:利用代码生成KeyStore和TrustStore

将步骤三执行后的整个证书文件夹从Linux系统中拷贝出来,工程的resources目录下;

参考测试类:kona-pkix/src/test/java/com/tencent/kona/pkix/tool/KeyStoreToolTest.java

按照测试类中的方法即可生成client或server的KeyStore和TrustStore。

最终得到一个TrustStore和两个KeyStore(客户端和服务端)

johnshajiang commented 1 year ago

@xudong-1990 非常感谢如此细致的过程!

shihaor commented 11 months ago

谢谢两位老师,学到啦