接口加密是指在网络传输过程中,将数据进行加密,以保护数据的安全性。接口加密可以采用多种加密算法,如AES、DES、RSA等。测试接口加密的目的是验证接口加密算法的正确性和安全性。
1加密与加密算法
加密(Encrypt)是将目标文本转换成具有不同长度的、可逆的密文。也就是说加密算法是可逆的,而且其加密后生成的密文长度和明文本身的长度有关。所以如果被保护数据在以后需要被还原成明文,则需要使用加密。
在加密算法中又分为对称加密(symmetric encryption)和非对称加密(asymmetric encryption)
2对称加密
对称加密采用了对称密码编码技术,它的特点是加密和解密都是用同一个密钥,这种方法在密码学中叫做对称加密算法.
对称加密算法使用起来简单快捷,密钥较短,且破译困难,除了数据加密标准(DES),另一个对称密钥加密系统是国际数据加密算法(IDEA),它比DES的加密性好,而且对计算机功能要求也没有那么高.
常见的对称加密算法有DES、3DES、Blowfish、IDEA、RC4、RC5、RC6和AES
注意: 因为前端的透明性,对于登录密码等敏感信息,就不要使用JavaScript来进行对称加密. 因为别人可以从前端得到密匙后,可以直接对信息进行解密!
(1)甲方选择某一种加密规则,对信息进行加密; (2)乙方使用同一种规则,对信息进行解密。 由于加密和解密使用同样规则(简称"密钥"),这被称为"对称加密算 法"(Symmetric-key algorithm)。 这种加密模式有一个最大弱点:甲方必须把加密规则告诉乙方,否则无 法解密。保存和传递密钥,就成了最头疼的问题。3非对称加密
非对称加密算法需要两个密钥:
公钥(publickey)和私钥(privatekey)
公钥与私钥是一对,如果用公钥对数据进行加密,只有用对应的私钥才能解密;如果用私钥对数据进行加密,那么只有用对应的公钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。
非对称加密算法实现机密信息交换的基本过程是:甲方生成对密钥并将其中的一把作为公钥向其它方公开;得到该公钥的乙方使用该密钥对机密信息进行加密后再发送给甲方;甲方再用自己保存的另一把专用密钥对加密后的信息进行解密。甲方只能用其专用密钥解密由其公钥加密后的任何信息。
常见的非对称加密算法有:RSA、ECC(移动设备用)、Diffie-Hellman、El Gamal、DSA(数字签名用)
(1)乙方生成两把密钥(公钥和私钥)。公钥是公开的,任何人 都可以获得,私钥则是保密的。 (2)甲方获取乙方的公钥,然后用它对信息加密。 (3)乙方得到加密后的信息,用私钥解密。 1976年,两位美国计算机学家Whitfield Diffie 和 Martin Hellman,提出了一种崭新构思,可以在不直接传递密钥的情况下,完 成解密。这被称为"Diffie-Hellman密钥交换算法"。这个算法启发 了其他科学家。人们认识到,加密和解密可以使用不同的规则,只要这 两种规则之间存在某种对应关系即可,这样就避免了直接传递密钥。 这种新的加密模式被称为"非对称加密算法"。4单向散列
哈希加密:
哈希(Hash)是将目标文本转换成具有固定长度的字符串(或叫做消息摘要)。 当输入发生改变时,产生的哈希值也是完全不同的。从数学角度上讲,一个哈希算法是一个多对一的映射关系,对于目标文本 T,算法 H 可以将其唯一映射为 R,并且对于所有的 T,R 具有相同的长度,所以 H 不存在逆映射,也就是说哈希算法是不可逆的。
基于哈希算法的特性,其适用于该场景:被保护数据仅仅用作比较验证且不需要还原成明文形式。比较常用的哈希算法是 MD5 和 SHA1。我们比较熟悉的使用哈希存储数据的例子是:当我们登录某个已注册网站时,在忘记密码的情况下需要重置密码,此时网站会给你发一个随机的密码或者一个邮箱激活链接,而不是将之前的密码发给你,这就是因为哈希算法是不可逆的。
需要注意的是:在 Web 应用中,在浏览器中使用哈希加密的同时也要在服务端上进行哈希加密。
服务端哈希加密原因: 一方面因为不需要将密文解密成明文来比对密码,另一方面是一旦加密算法和密钥泄露,那么整个用户资料库就相当于明文存储了。如果前端传过来的是明文,那么在注册时将其哈希,存入数据库。登录时,将密码哈希和数据库对应的数据比对,若一致则说明密码正确。
现在,对于简单的哈希算法的攻击方法主要有:寻找碰撞法和穷举法。所以,为了保证数据的安全,可以在哈希算法的基础上进一步的加密,常见的方法有:加盐、慢哈希、密钥哈希、XOR 等。
5数字签名
数字签名主要用于:确认信息来源于特定的主体且信息完整、未被篡改,发送方生成签名,接收方验证签名。
发送方: 首先计算目标文本的摘要(哈希值),通过私钥对摘要进行签名,将目标文本和电子签名发送给接收方。
接收方: 验证签名的步骤如下:
1. 通过公钥破解电子签名,得到摘要 D1 (如果失败,则信息来源主体校验失败);
2. 计算目标文本摘要 D2;
3. 若 D1 === D2,则说明目标文本完整、未被篡改。
数字签名与非对称加密区别:
非对称加密(加密/解密):公钥加密,私钥解密
数字签名(签名/验证):私钥签名,公钥验证
加密签名接口实战
01使用digest函数进行散列
摘要函数在特定的哈希算法中返回加密的值,并带有可选的salt,大写字母和变量名。
02使用commons-codec进行加密处理
什么是commons-codec
Apache Commons Codec软件包包含用于各种格式(例如Base64和 Hexadecimal)的简单编码器和解码器。除了这些广泛使用的编码器 和解码器之外,编解码器软件包还维护了语音编码实用程序的集合。 JMeter内置了commons-codec的jar包路径在JMeter_home的lib 目录下。 JMeter5.2.1使用的commons-codec-1.13.jar使用commons-codec进行加密
1)URL编码
System.out.println(URLEncoder.encode("原文", "UTF- 8"));2)MD5
MessageDigest md = MessageDigest.getInstance("MD5"); // JDK提供的MD5方法 byte[] md5Bytes = md.digest("原文".getBytes()); // 加密字节序列 得到 128个比特的摘要,即16字节 System.out.println(Hex.encodeHex(md5Bytes)); // 每4 个比特转成一位16进制数 System.out.println( DigestUtils.md5Hex("原文")); // Apache common codec 提供的MD5方法,最终调用的还是JDK3)SHA
//SHA-1(160比特)、SHA2(SHA-256、SHA-384、SHA-512) MessageDigest md = MessageDigest.getInstance("SHA- 256"); // JDK提供的SHA方法 byte[] md5Bytes = md.digest("原文".getBytes()); System.out.println(Hex.encodeHex(md5Bytes)); System.out.println( DigestUtils.sha256Hex("原文")); // Apache common codec 提供的SHA方法,最终调用的还是JDK4)Base64
BASE64Encoder encoder = new BASE64Encoder(); // JDK 提供 String enStr = encoder.encode("原文".getBytes()); // 编码 enStr = base64Img.replaceAll("[\\s*\t\n\r]", ""); // 去掉可能有的换行符 System.out.println(enStr); BASE64Decoder decoder = new BASE64Decoder(); System.out.println(new String(decoder.decodeBuffer(enStr))); // 解码 byte[] result = Base64.encodeBase64("原 文".getBytes()); // Apache common codec提供 System.out.println(new String(Base64.decodeBase64(result))); // 解码5)AES
// 生成key KeyGenerator kg = KeyGenerator.getInstance("AES"); kg.init(128); // 确定密钥长度 byte[] keyBytes = kg.generateKey().getEncoded(); // 格式化key Key key = new SecretKeySpec(keyBytes, "AES"); Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); // 确定算 法 cipher.init(Cipher.ENCRYPT_MODE, key); // 确定密钥 byte[] result = cipher.doFinal("原文".getBytes()); // 加密 System.out.println(Base64.encodeBase64String(result) ); // 不进行Base64编码的话,那么这个字节数组对应的字符串就 是乱码 cipher.init(Cipher.DECRYPT_MODE, key); // 进入解密模式 System.out.println(new String(cipher.doFinal(result))); // 解密6)RSA
// 生成密钥对 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); keyPairGenerator.initialize(512); KeyPair keyPair = keyPairGenerator.generateKeyPair(); RSAPublicKey rsaPublicKey = (RSAPublicKey)keyPair.getPublic(); RSAPrivateKey rsaPrivateKey = (RSAPrivateKey)keyPair.getPrivate(); // 格式化私钥 PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded()); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec); Cipher cipher = Cipher.getInstance("RSA"); // 确定算 法 cipher.init(Cipher.ENCRYPT_MODE, privateKey); // 确 定加密密钥 byte[] result = cipher.doFinal("原文".getBytes()); // 加密 System.out.println(Base64.encodeBase64String(result) ); // 格式化公钥 X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey.getEncoded()); keyFactory = KeyFactory.getInstance("RSA"); PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec); cipher = Cipher.getInstance("RSA"); // 确定算法 cipher.init(Cipher.DECRYPT_MODE, publicKey); // 确 定公钥 System.out.println(new String(cipher.doFinal(result))); // 解密