在线支付系列支付安全之对称和非对称加密

Posted 云烟成雨TD

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在线支付系列支付安全之对称和非对称加密相关的知识,希望对你有一定的参考价值。

有道无术,术尚可求,有术无道,止于术。

文章目录

前言

支付和金钱挂钩,支付安全显得尤为重要,微信、支付宝等第三方支付公司,为了确保支付安全问题,都下足了不少功夫,其底层还是和信息安全密切挂钩,所以在这之前,我们需要了解各种安全机制,才能更好地了解支付流程和安全性问题。

信息安全

信息安全是一个很广泛的概念,涉及计算机和网络系统的各个方面。从总体上来讲,信息安全有5个基本要素∶

  1. 机密性∶确保信息不暴露给未授权的实体或进程。

  2. 完整性∶只有得到允许的人才能够修改数据,并能够判别数据是否已被篡改。

  3. 可用性∶得到授权的实体在需要时可访问数据。

  4. 可控性∶可以控制授权范围内的信息流向和行为方式。

  5. 可审查性∶对出现的安全问题提供调查的依据和手段。

加密机制

数据加密即对明文(未经加密的数据)按照某种加密算法(数据的变换算法)进行处理,而形成难以理解的密文(经加密后的数据)。即使密文被截获,截获方也无法或难以解码,从而防止泄露信息。

按照加密密钥和解密密钥的异同,有两种密钥体制,分别是对称密码体制非对称密码体制

核心概念

1、明文

加密前的消息叫明文(plain text)。比如小明给小红发送一封情书没有加密,只要被截取,那么会直接看到明文的内容信息。连篇的土味情话被看到,盗信者直呼辣眼睛😭😭😭

2、密文

加密后的文本叫密文(cipher text)。为了防止别人看到,小明对情书内容进行加密,加密后内容变成了不可读的内容,就算被窃取,盗信者也无法看懂其内容。

3、密钥

拥有钥匙的人,使用钥匙将明文变为密文,使用钥匙将密文解析为明文,这把钥匙叫做秘钥(key)。

4、加密

使用秘钥,将明文变为密文的过程叫做加密(encrypt)。

5、解密

使用秘钥,将密文还原为明文的过程叫做解密(decrypt)。

6、加密算法

加密算法是一种密码学算法,就是指将明文变成密文的加密技术。所有的加密算法都是公开的,而算法使用的密钥则必须保密。

对称加密

对称加密加密和解密采用相同的密钥。因为只使用一个密钥,密钥必须保密,一旦被窃取,消息会被破解。其优点是运算速度快。

它要求发送方和接收方在安全通信之前,商定一个密钥。对称算法的安全性依赖于密钥,泄漏密钥就意味着任何人都可以对他们发送或接收的消息解密,所以密钥的保密性对通信的安全性至关重要。

工作流程

  1. 小明使用某种加密算法生成一个秘钥,并将这个秘钥给小红。
  2. 小明使用秘钥将情书进行加密,变为密文,并发送给小红。
  3. 小红收到情书后,使用秘钥将密文还原为明文。

非对称加密

非对称加密公钥私钥两个概念,私钥自己拥有,不能给别人,公钥公开。比对称加密安全,但是运算速度更慢。

工作流程

  1. 小红使用某种加密算法生成一对密钥(公钥和私钥),并将这个公钥给小明。
  2. 得到公钥的小明使用该密钥对机密信息进行加密后再发送给小红。
  3. 小红用自己的专用私钥对加密后的信息进行解密。

    在传输过程中,即使攻击者截获了传输的密文,并得到了公钥,也无法破解密文,因为只有小红的私钥才能解密密文。

JCE

JCEJava Cryptography Extension三个单词的缩写,译为Java 加密扩展,是JDK 1.4 提供的一个用于加密、密钥生成算法等功能的扩展包。


接下来我们使用 JCE 实现对称、非对称加解密。

对称加解密

1. 创建密钥

创建密钥需要创建一个javax.crypto.KeyGenerator密钥生成器对象,KeyGenerator提供对称密钥生成器的功能,使用此类的 getInstance 方法获取实例对象。

KeyGenerator 对象可重复使用,也就是说,在生成密钥后,可以重复使用同一个KeyGenerator对象来生成更多的密钥。

KeyGenerator.getInstance()方法返回指定算法的密钥生成器对象,三个重载方法说明如下:

// 返回生成指定算法的秘密密钥的 KeyGenerator 对象。
// algorithm:密钥算法的标准名称
public static final KeyGenerator getInstance(String algorithm) throws NoSuchAlgorithmException
// 返回生成指定算法的秘密密钥的 KeyGenerator 对象。
// algorithm:密钥算法的标准名称
// provider:提供者的名称
public static final KeyGenerator getInstance(String algorithm,String provider)throws NoSuchAlgorithmException,NoSuchProviderException
// 返回生成指定算法的秘密密钥的 KeyGenerator 对象。
// algorithm:密钥算法的标准名称
// provider:提供者对象
public static final KeyGenerator getInstance(String algorithm,Provider provider)throws NoSuchAlgorithmException

该方法需要两个重要参数:算法名称、服务提供者。

加密服务提供者简称CSPjava.security.Provider是所有安全服务提供程序的基类。在进行加解密运算时,需要指定一个CSPJDK默认安装并配置了一个或多个提供程序,也可以注册第三方或自定义服务提供者(例如第三方加密机)。如果没有指定该参数,会从可用的提供者中选取第一个。

通过以下代码,可以获取当前JDK环境所有提供者:

Provider[] providers = Security.getProviders();
  for (Provider provider : providers) 
 	String name = provider.getName();
 	double version = provider.getVersion();
	System.out.println(name + ": " + version);

// 输出结果
SUN1.8
SunRsaSign1.8
SunEC1.8
SunJSSE1.8
SunJCE1.8
SunJGSS1.8
SunSASL1.8
XMLDSig1.8
SunPCSC1.8
SunMSCAPI1.8

算法名称:密钥算法的标准名称。常用的对称算法有:AES、3DES、SM1(国密JDK不支持)、SM4(国密)等。

算法名称秘钥长度加密强度性能版权
DES56美国
3DES168美国
IDEA128瑞士
AES128 192 256美国
SM1128中国
SM4128中国

创建了秘钥生成器后,还需要调用init 方法进行初始化。常用方法:

// 初始化此密钥生成器,使其具有确定的密钥大小。
// 参数:keysize  密钥长度。这是特定于算法的一种规格,是以位数为单位指定的。
public final void init(int keysize)

密钥长度是一个重要的参数,每种算法都有其支持的长度,长度越长的情况下,暴力破解的时间就越长。长度单位为位(bit)

生成对称密钥代码如下:

// 获取密钥生成器,指定算法为AES
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
// 初始化
keyGenerator.init(128);
// 生成公钥
SecretKey secretKey = keyGenerator.generateKey();
// 打印秘钥:LDDoCClZOvP9ZncFM19jZg==
byte[] keyEncoded = secretKey.getEncoded();
System.out.println(Base64.getEncoder().encodeToString(keyEncoded));

2. 加密

在上一步骤中,我们生成了一个Base64编码的秘钥字符串:LDDoCClZOvP9ZncFM19jZg==,接下来我们使用该秘钥进行加密。

加解密时,需要使用JCE中的javax.crypto.Cipher对象。此类为加密和解密提供密码功能。它构成了Java Cryptographic Extension (JCE) 框架的核心。

调用getInstance方法获取该对象实例,该方法需要一个字符串参数。

// 返回实现指定转换的 Cipher 对象。此方法从首选 Provider 开始遍历已注册安全提供者列表。
// 参数:transformation - 转换的名称,例如 DES/CBC/PKCS5Padding。
public static final Cipher getInstance(String transformation)

transformation 翻译过来是转换的意思,可以理解为一个转换规则,由三部分组成算法/加密模式/填充规则

算法就是标准的算法名称,之间我们已经介绍过了。

加密模式主要有以下两种:

  • ECB(电码本模式),将明文分成若干小段, 然后对每小段进行加密
  • CBC(密码分组链接模式),先将明文切分成若干小段,然后每一小段与初始块或者上一段的密文段进行异或运算后,再使用密钥进行加密

填充规则:在分组密码中,当数据长度不符合分组长度时,需要按一定的方式,将尾部明文分组进行填充,这种将尾部分组数据填满的方法称为填充(Padding)。

填充规则主要有以下几种:

  • NOPADDING:即不填充,要求明文的长度,必须是加密算法分组长度的整数倍。
  • ANSIX9.23:在填充字节序列中,最后一个字节填充为需要填充的字节长度,其余字节填充0。
  • PKCS5PADDING:在填充字节序列中,每个字节填充为需要填充的字节长度。

以下列举了几种算法对应的转换名称:

算法转换名称
AESAES/CBC/NoPadding
AESAES/CBC/PKCS5Padding
AESAES/ECB/NoPadding
AESAES/ECB/PKCS5Padding
DESDES/CBC/NoPadding
DESDES/CBC/PKCS5Padding
DESDES/ECB/NoPadding
DESDES/ECB/PKCS5Padding

通过以上知识,加密代码如下:

        // 原文
        String message = "爱老虎油~";
        // Base64编码的秘钥字符串
        String keyBase64 = "LDDoCClZOvP9ZncFM19jZg==";
        // 获取Cipher 对象
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        // 将秘钥字符串转为秘钥对象
        SecretKey keySpec = new SecretKeySpec(Base64.getDecoder().decode(keyBase64), "AES");
        // 初始化,设置为加密模式,并传入秘钥
        cipher.init(Cipher.ENCRYPT_MODE, keySpec);
        // 加密运算
        byte[] cipherData = cipher.doFinal(message.getBytes(StandardCharsets.UTF_8));
        // 打印密文:SJ+6fnHAWt9ui7Pq3AlFmg==
        System.out.println("密文:" + Base64.getEncoder().encodeToString(cipherData));

3. 解密

解密就比较简单了,使用秘钥,调用Cipher 对象进行解密即可,代码如下:

        // 解密
        // 密文
        String enBase64Message="SJ+6fnHAWt9ui7Pq3AlFmg==";
        // Base64编码的秘钥字符串
        String enKeyBase64 = "LDDoCClZOvP9ZncFM19jZg==";
        // 获取Cipher 对象
        Cipher deCipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        // 将秘钥字符串转为秘钥对象
        SecretKey deKeySpec = new SecretKeySpec(Base64.getDecoder().decode(enKeyBase64), "AES");
        // 初始化,设置解密模式,并传入秘钥
        deCipher.init(Cipher.DECRYPT_MODE, deKeySpec);
        // 解密运算
        byte[] bytes = deCipher.doFinal(Base64.getDecoder().decode(enBase64Message));
        // 打印明文
        System.out.println("明文:" + new String(bytes));

执行结果如下:

密文:SJ+6fnHAWt9ui7Pq3AlFmg==
明文:爱老虎油~

非对称加解密

1. 创建密钥

使用KeyPairGenerator.getInstance()获取一个秘钥生成器,参数类型和对称秘钥一样,区别在于算法名称不一样。

常见的非对称加密算法有:

  • RSA:性能比较快,如果想要较高的加密难度,需要很长的秘钥。
  • ECC:基于椭圆曲线提出。是目前加密强度最高的非对称加密算法。
  • SM2:同样基于椭圆曲线问题设计。最大优势就是国家认可和大力支持。

代码如下

        // 获取非对称密钥生成器
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        // 初始化
        keyPairGenerator.initialize(512);
        // 生成秘钥对
        KeyPair keyPair = keyPairGenerator.generateKeyPair(); // 获取内部密钥对
        PrivateKey privateKey = keyPair.getPrivate(); // 私钥
        PublicKey publicKey = keyPair.getPublic(); // 公钥
        // 打印秘钥:
        System.out.println("公钥:" + Base64.getEncoder().encodeToString(publicKey.getEncoded()));
        System.out.println("私钥:" + Base64.getEncoder().encodeToString(privateKey.getEncoded()));

执行结果

公钥:MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAL8SAEW1o3lMg4XVQi29n7XqQ02ei0voeKcXvj+bVH1Fu+8W9CzSLpnlHHQgL9bl8Kly/5/y0TgE+NBxsrdfZo8CAwEAAQ==
私钥:MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEAvxIARbWjeUyDhdVCLb2ftepDTZ6LS+h4pxe+P5tUfUW77xb0LNIumeUcdCAv1uXwqXL/n/LROAT40HGyt19mjwIDAQABAkEAm4TsYdERaSbFGsbVIePpPimadHAqkzN6GQ8zVBR7NaaEeeFjZ/XX/FmNTvrKp2IXN5p0d0LZDOUPq3UL/nzpQQIhAP3JnMQBa9yeb3NzmCguaDwty8175sEDsB/NJLrULuehAiEAwLxrkZItOaoFRV6c78qPsHQGKSTQQBAFS2vycehW4C8CIQDH6wwM8zmunzgYcFTKQlRmI4VKJ3JNVcRmKMnoSsFwQQIgTob2lPMn9gyt5RuteY3giZZcRDs5lkBwx9ANkheF/gUCIAwBGYCzZHNsEr6PIfImrwxRLs/MFPbbQAHpUQaLaWL9

2. 公钥加密

使用公钥对原文数据进行加密。

        // 使用公钥加密
        // 原文
        String message = "爱老虎油~";
        // Base64编码的公钥字符串
        String publicKeyBase64 = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAMEC2gOpKGTzCdJ4flb6Oj9QmbwVANmwLn0zBkZINepGEeWnvORxlteakSK03O2XgtHSGyW4r520KBtvKEcdFAECAwEAAQ==";
        // 获取Cipher 对象
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        // 将公钥字符串转为公钥对象
        X509EncodedKeySpec bobPubKeySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(publicKeyBase64));
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey publicKeyByValue = keyFactory.generatePublic(bobPubKeySpec);
        // 初始化,设置为加密模式,并传入公钥
        cipher.init(Cipher.ENCRYPT_MODE, publicKeyByValue);
        // 加密运算
        byte[] cipherData = cipher.doFinal(message.getBytes(StandardCharsets.UTF_8));
        // 打印密文:mMzlg+65E1QKJi+zOVdyzbYrq526fOd7ir0Zlkbvo2q37iGvrMiq/y9P4teBtPe9PRJF7HCsmezZ3/M0aiQbyw==
        System.out.println("密文:" + Base64.getEncoder().encodeToString(cipherData));

3. 私钥解密

使用私钥对密文数据进行解密。

        // 使用私钥解密
        // 密文
        String enBase64Message = "mMzlg+65E1QKJi+zOVdyzbYrq526fOd7ir0Zlkbvo2q37iGvrMiq/y9P4teBtPe9PRJF7HCsmezZ3/M0aiQbyw==";
        // Base64编码的私钥字符串
        String privateKeyBase64 = "MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEAwQLaA6koZPMJ0nh+Vvo6P1CZvBUA2bAufTMGRkg16kYR5ae85HGW15qRIrTc7ZeC0dIbJbivnbQoG28oRx0UAQIDAQABAkEAmQgjx6dFadTxQrlaoqe/qxfC7MdSZ0czdP0RyoPSi64k942Rj46in5zDw60SynysVvMmVinxPPFS+6rv5kIWaQIhAPMXt8l7jPGmF6pYTmE2cx9OjB4Q9q8uhfIKZc0E7T9HAiEAy0JkNwSVxK76I9mFZpoRSfH37xAqLyUKhdCRAn5fBncCIQDGw3Pg6Ia750SeYgnkbrL+vCjRRKmPX4jh+SJ32jlqbQIgIXe6FpELtAn3qAV+AKnnpNxRraxktcSMmgIAjn+OV/sCIFlpFzkKXkW2cTv6oVHbFkqgrDPhTAXbshsa/U301Oac";
        // 获取Cipher 对象
        Cipher deCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        // 将私钥字符串转为私钥对象
        PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKeyBase64));
        KeyFactory privateKeyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKeyByValue = privateKeyFactory.generatePrivate(privateKeySpec);
        // 初始化,设置解密模式,并传入私钥
        deCipher.init(Cipher.DECRYPT_MODE, privateKeyByValue);
        // 解密运算
        byte[] bytes = deCipher.doFinal(Base64.getDecoder().decode(enBase64Message));
        // 打印明文: 明文:爱老虎油~
        System.out.println("明文:" + new String(bytes));

对称加密和非对称加密

对称加密和非对称加密


HTTP是一种不安全(嗅探、篡改)的协议
所以需要引入HTTPS(HTTP + SSL)

对称加密

加密密钥 = 解密密钥
优点:速度较快,缺点:密钥的传输和保管也是不安全的(可能会有中间人获取)

所以还是有可能使用一个不安全的密钥进行传输

非对称加密

非对称加密:加密密钥!=解密密钥
虽然速度较慢,但是不怕密钥泄露
如何保证在传输的时候,没有中间人呢?

数字签名

数字签名,数字摘要——对数据进行哈希,利用相同的数,哈希值一定相同
如果签名的值相同,那么数据大概率没被篡改过

CA证书

引入公证处,保证

以上是关于在线支付系列支付安全之对称和非对称加密的主要内容,如果未能解决你的问题,请参考以下文章

如何保证数据的安全?对称和非对称加密,身份认证,摘要算法,数字证书等傻傻分不清?波哥图解带你彻底掌握

7 Go密码学(四) 非对称加密之RSA

Java安全系列-RSA加密

Java安全系列-RSA加密

对称加密和非对称加密

对称加密和非对称加密