密码控件解密流程和原理

密码控件解密流程和原理

近期做了一些密码控件相关的需求,这里整理一下密码控件后端服务的加解密原理,以及引申介绍了一些二进制和base64编码的一些关系,其实加解密原理离不开https,本文没有描写https的部分,大家有空也可以了解一下.

1.1 RSA

在客户端的键盘安全控件内部实现网银会话绑定加密功能,主要功能实现如下,根据上图流程所示,服务器端生成一个公私钥对(Kp,Ks),键盘安全控件内置其公钥Kp。建立会话时,在客户端,安全控件内部生成随机数Rc,在服务器端生成随机数Rs。随后由服务器维护随机数Rs与会话的绑定,并将随机数Rs发给 客户端。客户端安全控件接收Rs后,将Rs与自己得Rc进行拼接,得到新的随机数Rs+Rc=R。此随机数R将作为后面的数据的对称加密的密钥。首先,在安全控件内部,用R对文明数据Dp(键盘输入的密码口令等)进行对称加密,形成密文Dc,加密算法采用DES等对称算法。其次,将客户端自己生成的随机数Rc用服务器的公钥进行加密。最后,将用公钥加密后Rc、以及用R加密后的数据一同发到服务器端。

服务器端收到数据后,用自己的私钥对Rc密文进行解密后得到Rc,然后用保存的Rs与Rc进行拼接得到R,再用R对数据密文进行解密。

image-20201110105612027

1.2 国密

如果加密算法标示为国产算法,加密方式为:客户端产生16字节随机数Rc,服务器产生16字节随机数Rs。取Rs的前8字节在前以及Rc的前8字节在后,组成16字节的对称密钥R。取Rs的后8字节在前以及Rc的后8字节在后,组成16字节作为初始向量。以16字节为加密单位块长度、PKCS#7 填充模式对密码使用SM4加密。SM4加密采用CBC模式。

image-20201110105708961

2.1随机数生成

随机数生成代码

Base64.toBase64String(SecureRandoms.getInstance().genBytes(16));

import java.security.SecureRandom;
SecureRandom random = new SecureRandom();
byte[] bytes = new byte[16];
random.nextBytes(bytes);
String toBase64String = Base64.toBase64String(bytes);

3引申知识hex和base64

hex和base64 都是 把二进制数组变成可见字符的编码方式,在公钥,私钥保存成文本,生成签名值都会用到.

3.1hex

1.使用16个可见字符来表示一个二进制数组,编码后数据大小将x2
2.1个字符需要用2个可见字符来表示

 /**
     * 转换字节数组为16进制字串
     */
    public static String byteArrayToHexString(byte[] bytes) {
        String ret = "";
        for (int i = 0; i < bytes.length; i++) {
            String hex = Integer.toHexString(bytes[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            ret += hex.toUpperCase();
        }
        return ret;
    }


 /**
     * 将Hex String转换为Byte数组
     *
     * @param hexString the hex string
     * @return the byte [ ]
     */
    public static byte[] hexStringToBytes(String hexString) {
        if (StringUtils.isEmpty(hexString)) {
            return null;
        }
        hexString = hexString.toLowerCase();
        final byte[] byteArray = new byte[hexString.length() >> 1];
        int index = 0;
        for (int i = 0; i < hexString.length(); i++) {
            if (index > hexString.length() - 1) {
                return byteArray;
            }
            byte highDit = (byte) (Character.digit(hexString.charAt(index), 16) & 0xFF);
            byte lowDit = (byte) (Character.digit(hexString.charAt(index + 1), 16) & 0xFF);
            byteArray[i] = (byte) (highDit << 4 | lowDit);
            index += 2;
        }
        return byteArray;
    }

3.2 base64

1.使用64个可见字符来表示一个二进制数组,编码后数据大小变成原来的4/3
2.3个字符用4个可见字符来表示

常用的工具类:

  1. java.util.Base64(数据存在换行,会报错)

    jdk8内置的Base64解码器进行解析的时候,会抛出java.lang.IllegalArgumentException: Illegal base64 character a异常.

    这个类包含了base64编码格式的编码方法和解码方法,而且实现是按照rfc4648和rfc2045两个协议来实现的。
    编码和解码操作是照着两个协议中的’Table 1’中指定的’The Base64 Alphabet’来的。编码器不会添加任何换行符,解码器只会处理’The Base64 Alphabet’范围内的数据,如果不在这个范围内,解码器会拒绝处理。

  2. org.apache.commons.codec.binary.Base64.decodeBase64(这个兼容性更好,建议使用这个.)

    Apache Common中的org.apache.commons.codec.binary.Base64类是基于rfc2045实现的,根据类注释可以了解到此实现解码时忽略了所有不在the base64 alphabet范围内的字符,所以该实现可以处理包含换行符的base64编码结果。

Base64.getEncoder().encodeToString(Files.readAllBytes(Paths.get("C:\\Program Files (x86)\\360\\360zip\\utils\\360Feedback.exe")));
Base64.getDecoder().decode(reqVO.getPhoto().replaceAll("-", "+"));
# apache的base64工具类
org.apache.commons.codec.binary.Base64.decodeBase64(reqVO.getPhoto().replaceAll("-", "+"));

maven坐标

<dependency>
  <groupId>commons-codec</groupId>
  <artifactId>commons-codec</artifactId>
  <version>1.2</version>
</dependency>

4.国产密码算法

国密即国家密码局认定的国产密码算法。主要有SM1,SM2,SM3,SM4。密钥长度和分组长度均为128位。

SM1为对称加密。其加密强度与AES相当。该算法不公开,调用该算法时,需要通过加密芯片的接口进行调用。

SM2为非对称加密,基于ECC。该算法已公开。由于该算法基于ECC,故其签名速度与秘钥生成速度都快于RSA。ECC 256位(SM2采用的就是ECC 256位的一种)安全强度比RSA 2048位高,但运算速度快于RSA。

SM3消息摘要。可以用MD5作为对比理解。该算法已公开。校验结果为256位。

SM4无线局域网标准的分组数据算法。对称加密,密钥长度和分组长度均为128位。

不太严谨的使用方式类比:

国产密码算法开源密码算法加密方式
SM1AES对称加密
SM2RSA非对称加密
SM3MD5/SHA-256消息摘要
SM43DES对称加密

参考文档

  1. https://www.jianshu.com/p/0636ee193e7f?tdsourcetag=s_pcqq_aiomsg
  2. https://github.com/ZZMarquis/gmhelper
  3. https://baike.baidu.com/item/SM4.0/3901780?fr=aladdin
  4. 使用java8的java.util.Base64报“java.lang.IllegalArgumentException: Illegal base64 character d”的问题

如果觉得文章对您有用,可以关注我的公众号 程序和猫 , 更加方便的交流.

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值