小程序安全键盘&SM2解密方式

这篇具有很好参考价值的文章主要介绍了小程序安全键盘&SM2解密方式。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

小程序安全键盘&SM2解密方式

转载请著名出处:https://www.cnblogs.com/funnyzpc/p/17572445.html

SM2基本信息

  • 私钥(primary key)
6082011f17b21dab7da93f2dc1a739b530b969171c7116bebb0535a953e20bae
  • 公钥(public key)
041708d05635b28264a919b89b1370b1517e51d19851c93b49bbaa54521ca4fec0d384069374dcedd846abb55b9920cc4fdf2270b4283b30de55344a66cb3f4334
  • 加密内容
hello\nyouth\n12334
  • 需要的加密库(java)
		<dependency>
			<groupId>org.bouncycastle</groupId>
			<artifactId>bcprov-jdk15on</artifactId>
			<version>1.67</version>
		</dependency>
		<dependency>
			<groupId>org.bouncycastle</groupId>
			<artifactId>bcpkix-jdk15on</artifactId>
			<version>1.67</version>
		</dependency>

理论上版本越高越好,如果版本较低可能出现加解密问题,这点是要注意的~

  • 三方实现库(gmhelper)

https://github.com/ZZMarquis/gmhelper

👏这里感谢大神Lijun Liao写的库,不胜感激之至~

以上内容在后面会用到,这里先声明~

首先先看看小程序官方文档

[安全键盘]文档(https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/safe-password.html)

关键内容:

'V02_' + sm2(header + timestamp + '\0' + pbkdf_hmac_hex(password, salt) + '\0' + nonce + '\0' + 随机数)

就以上,我们可以得出一些信息:

  • 1.解密前必须要削掉V02_再行解密
  • 2.sm2函数内这几项headertimestamp\0nonce随机数对于后端来说并没有鸟用
  • 3.salt这个是函数pbkdf_hmac_hex的盐,是否能去掉不得而知~
  • 4.函数pbkdf_hmac_hex看似是 未知算法pbkdf+哈希算法hmac+16进制hex 的综合
  • 5.如果可以自定义pbkdf_hmac_hex函数,理论上后端是可以拿到明文password(事实上不能)😂
  • 6.Windows_SMCryptoTools/Mac_SMCryptoTools是的好东西,后面开发得用上😀

好了,我们先从Windows_SMCryptoTools/Mac_SMCryptoTools这个工具开始一步步打通密文

Windows_SMCryptoTools/Mac_SMCryptoTools生成密钥对(公钥&私钥)

小程序安全键盘&SM2解密方式

小程序安全键盘&SM2解密方式

接下来用到的公钥以及私钥以及本文在开头就已提供 => SM2基本信息

先看看 SM2 Encrypt/Decrypt

小程序安全键盘&SM2解密方式

小程序安全键盘&SM2解密方式

格式选择里面有四种模式,其中C1C3C2SM2的其中一种模式 ASN1SM2的文本编码方式,事实上这些也是微信键盘所使用的编码加密方式

公钥加密

先看到工具的明文部分是HEX(16进制)的,好的这就按照工具的逻辑将明文做16进制转换

  • 代码
import org.bouncycastle.util.encoders.Hex;

// 明文需要转为16进制字符串 SRC=hello\nyouth\n12334
public byte[] buildData(){
    byte[] encode = Hex.encode(SRC);
    // return new String(encode,StandardCharsets.UTF_8);
    return encode;
}

这是16进制编码后的字符串:68656c6c6f5c6e796f7574685c6e3132333334

然后将HEX编码字符使用加解密工具Windows_SMCryptoTools/Mac_SMCryptoTools计算到16进制密文:

307B0220440D1CF67E1E78DB263BF4AC904B7CFE1D268954961DF042E0B3C683D0E851B502201047009A29B2900047333862A2F5E933503BFDD7F4F140FE2715053FD6BE07F10420B8C18A7BD0FFEF2214D2F879324A1E399D0D4B44DE0113ED5E06A8E4A65410850413A987567A5B30A79F81F02512BE1F8F1732E2E4

记住加密后得到的一定是 16进制密文 这点很重要,在后面会用到!

私钥解密

上面我们通过工具及自定义编码方式得到了最后的密文
这个密文怎么解 需要先理一下思路:

  • 1.由于明文在加密的过程中做了HEX,所以肯定涉及到解16进制编码
  • 2.由于ASN1是一种文本编码方式,这个东东可能是是在SM2加密前也可能是加密后做的编码行为
  • 3.基于[2]知道开发需要一套能实现SM2以及ASN1编码的功能的库

首先准备一个实现库,这里我用的是gmhelper(感谢 Lijun Liao )

// 用到的三方库
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
import org.bouncycastle.util.encoders.Hex;
import org.junit.jupiter.api.Test;

import java.nio.charset.StandardCharsets;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

    @Test
    public void test03()throws Exception{
        // 密文hex
        String hex_enc = "307B0220440D1CF67E1E78DB263BF4AC904B7CFE1D268954961DF042E0B3C683D0E851B502201047009A29B2900047333862A2F5E933503BFDD7F4F140FE2715053FD6BE07F10420B8C18A7BD0FFEF2214D2F879324A1E399D0D4B44DE0113ED5E06A8E4A65410850413A987567A5B30A79F81F02512BE1F8F1732E2E4";
        byte[] enc = Hex.decode(hex_enc);
        // 私钥参数类
        ECPrivateKeyParameters ecPrivateKeyParameters = BCECUtil.createECPrivateKeyParameters(私钥, SM2Util.DOMAIN_PARAMS);
        // 这个很重要,一定要先解ASN1(ASN1就是DER编码的一种实现方式)
        byte[] enc_bytes = SM2Util.decodeDERSM2Cipher(enc);
        byte[] decryptData = SM2Util.decrypt( ecPrivateKeyParameters,enc_bytes );
        // 上面得到的是byte数组,这里需转String
        String dec_str = new String(decryptData, StandardCharsets.UTF_8);
        System.out.println("SM2 decrypt result: " + dec_str);
    }

最终得到我们的原始明文:

SM2 decrypt result: hello\nyouth\n12334

以上测试通过后,标志着可以进行前后端联调了~

回到题目

首先:微信安全键盘的目的是提供一种安全的密码输入环境,这个过程似乎并不希望引用所有者能得到使用者的明文密码,所以我在同事的配合测试下也大致印证了这个猜想.故:如果某些场景下确实需要得到用户输入的明文,则不推荐安全键盘~

我们通过微信官方社区以及三方库的折腾终于解出了安全键盘的密文,当然囖,这个密文是hash过的,以下是实现代码

  • 代码
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
import org.bouncycastle.util.encoders.Hex;
import org.junit.jupiter.api.Test;

import java.nio.charset.StandardCharsets;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

    @Test
    public void test04()throws Exception{
        // 私钥   7fe1e04e1cb539640282f047809c2380570be2dd72513160602c04a128071e97
        // 公钥   041cb7b860ac9c353f460cac7ddca32a01cce15ffacd567db0507e32ad769fbed50f071c332e9d7003d75e227ea4489c43d286ec30bbdc4882420faabe5e24f90c
        String privateKey = "7fe1e04e1cb539640282f047809c2380570be2dd72513160602c04a128071e97";
        String publicKey  = "041cb7b860ac9c353f460cac7ddca32a01cce15ffacd567db0507e32ad769fbed50f071c332e9d7003d75e227ea4489c43d286ec30bbdc4882420faabe5e24f90c";
//        String hex_enc = "V02_3081D002200154F7A5EAFDC714962A8061201A18EAB3589B1F44A9031E3E116630E221F107022024A19B7836FDD4A419C19ACB5A2D54EC9D27E4843977C8240D5A7E2F1CC0E17C0420C9616F97AD375F54F6FDDC64AA4C3409D0AC0BDC7FD85E7D77786A3F555097B90468D249FA7CB008C2F76690BD46625980B0B4E5BA4A7095D114F9652CEE06E0AC4320E4FD5D60D246FB7185046106B3EA486C37DD34EE8A52BBC026DBCE2EB86CCE900712C2068F4C81BEA5306181C07BF543F8AD39C881A25F54F3657603F38E14AB1C6C8B6AAAFEA0";
        String hex_enc = "3081D002200154F7A5EAFDC714962A8061201A18EAB3589B1F44A9031E3E116630E221F107022024A19B7836FDD4A419C19ACB5A2D54EC9D27E4843977C8240D5A7E2F1CC0E17C0420C9616F97AD375F54F6FDDC64AA4C3409D0AC0BDC7FD85E7D77786A3F555097B90468D249FA7CB008C2F76690BD46625980B0B4E5BA4A7095D114F9652CEE06E0AC4320E4FD5D60D246FB7185046106B3EA486C37DD34EE8A52BBC026DBCE2EB86CCE900712C2068F4C81BEA5306181C07BF543F8AD39C881A25F54F3657603F38E14AB1C6C8B6AAAFEA0";
        byte[] enc = Hex.decode(hex_enc);
        ECPrivateKeyParameters ecPrivateKeyParameters = BCECUtil.createECPrivateKeyParameters(privateKey, SM2Util.DOMAIN_PARAMS);
        byte[] decryptData = SM2Util.decrypt( ecPrivateKeyParameters,SM2Util.decodeDERSM2Cipher(enc) );
        String dec_str = new String(decryptData, StandardCharsets.UTF_8);
        System.out.println("SM2 decrypt result: " + dec_str);

    }

对于以上实现需要注意的是:

  • 1.解密前必须要削掉A02_开头字符
  • 2.解密后的明文中会有\0分割各个block,需要自行split
  • 3.明文在解密前以及解密后都是HEX(16进制)
  • 4.在开发前建议使用工具(Windows_SMCryptoTools/Mac_SMCryptoTools)先行测试,过不了工具这关联调肯定也是不行的!

虽然最终的代码实现几乎毫不费力,但这中间确实也付出了时间成本,主要是对加密具体算法比较陌生,以及微信官方没有sdk这就有些黑箱导致了实现的困难,再加上SM2&ASN1实现的资料太少太窄导致~🎈文章来源地址https://www.toymoban.com/news/detail-601767.html

到了这里,关于小程序安全键盘&SM2解密方式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • SM2 加解密 一文理清

    SM2 加解密 一文理清

    1. 给一个私钥的der文件。   通过命令查看公私钥数据。 F:projectsimkeynowgmssl ec -inform der -in anca_ec_keypri.der -text Using configuration from C:Program FilesCommon FilesSSL/openssl.cnf read EC key Private-Key: (256 bit) priv:     90:8d:22:29:03:f2:8d:bf:45:20:ff:57:77:d4:a1:     cb:57:09:6b:99:45:51:62:bd:2b:d7:d3:60:b1:c

    2023年04月20日
    浏览(10)
  • SM2国密算法加解密

    接口安全设计原则的一个点就是数据不能明文传输,除了https这个必须的请求外,接口数据加密也是一个重要的方式,下面介绍一下SM2国密算法加解密的使用方式。 这里我就针对目前前后端分离架构的方式来简单介绍一下如何正确使用 SM2 算法对数据进行加解密,介绍分为后

    2024年02月11日
    浏览(32)
  • 前端sm2国密加密解密

    1.下载国密包 2.获取后端的公钥 注sm-crypto使用BC库加解密前端密钥与后端密钥是两队,非常规的base64密钥 前端公钥需要在前面加04占位否则无法解密 3.前端使用公钥进行加密 生成的加密串加04方便后端解密 4.前端使用私钥解密

    2024年02月11日
    浏览(53)
  • javascript实现SM2加密解密

    前提JavaWeb环境 前端代码 实现步骤 java

    2024年02月14日
    浏览(14)
  • 国密SM2前端加密解密示例

    目录 一、 安装sm2依赖 二、编写代码 1、data中绑定数据 2、公钥加密 3、私钥解密 4、按钮绑定一下,数据可见一下 三、完整代码 要改变的数据phone和过程数据copyphone,公钥publicKey和私钥privateKey 具体生成测试公钥私钥可参照SM2加解密 C1为65字节第1字节为压缩标识,这里固定为

    2024年02月03日
    浏览(47)
  • 前端使用国密sm2和sm4进行加解密

    国密SM:国密算法,即国家商用密码算法。是由国家密码管理局认定和公布的密码算法标准及其应用规范,其中部分密码算法已经成为国际标准。如SM系列密码,SM代表商密,即商业密码,是指用于商业的、不涉及国家秘密的密码技术。 安装SM加密依赖 SM2 封装 将sm2的加密解密

    2024年02月08日
    浏览(48)
  • 基于hutool 封装国密sm2,sm4 加解密算法

    基于hutool 封装国密sm2,sm4 加解密算法 1. 加入依赖包 2. 编码

    2024年02月13日
    浏览(15)
  • Java实现SM2前后端加解密

    Sm2加解密原理,非对称加密,公钥加密,私钥解密。公私钥对成对生成,加密端解密端各自保存。用公钥加密必须要用对应的私钥才能解密,保证安全性。 这里我们实现的功能是前端加密,后端解密,这样前端暴露了公钥,后端持有配对的私钥,保证安全性。 1.jsp引入sm2 2

    2024年02月11日
    浏览(12)
  • 前端国密加解密使用方法SM2、SM3、SM4

       国密算法,即国家商用密码算法。是由国家密码管理局认定和公布的密码算法标准及其应用规范,其中部分密码算法已经成为国际标准。如SM系列密码,SM代表商密,即商业密码,是指用于商业的、不涉及国家秘密的密码技术。      不多废话直接上干货 项目中 可能存在

    2023年04月09日
    浏览(44)
  • 国密SM2: 加解密实现 java代码完整示例

    国密SM2: 加解密实现 java代码完整示例

    目录  具体Java代码SM2算法加解密实现Demo: pom依赖引入 :  国家密码管理局于2010年12月17日发布了SM2算法,并要求现有的基于RSA算法的电子认证系统、密钥管理系统、应用系统进升级改造,使用支持国密SM2算法的证书。    基于ECC椭圆曲线算法的SM2算法,则普遍采用256位密钥

    2024年02月13日
    浏览(11)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包