接口安全加密传输(对称加密与非对称加密)

ゝ一纸荒年。 2022-01-28 13:34 596阅读 0赞

接口安全加密传输(对称加密与非对称加密)

URL特殊字符转码

对称加密与非对称加密

DES RSA加密原理

移动APP接口安全加密设计

基于令牌方式实现接口参数安全传输

验签 单向加密

URL转码:

不管是以何种方式传递url时,如果要传递的url中包含特殊字符,如想要传递一个+,但是这个+会被url会被编码成空格,想要传递&,被url处理成分隔符。

尤其是当传递的url是经过Base64加密或者RSA加密后的,存在特殊字符时,这里的特殊字符一旦被url处理,就不是原先你加密的结果了。

url特殊符号及对应的编码:



















































符号

url中的含义

编码

+

URL 中+号表示空格

%2B

空格

URL中的空格可以用+号或者编码

%20

/

分隔目录和子目录

%2F

?

 

 

 

 

 

 

 

分隔实际的URL和参数

%3F

%

指定特殊字符

%25

#

表示书签

%23

&

URL中指定的参数间的分隔符

%26

=

URL中指定参数的值

%3D

rpc远程通讯 实现加密有一些特殊字符 正好和http协议特殊字符形同 导致转成空格

localhost:8080/userName=1+1 这样的就接收到的是 1 1 空格代替了!

Java中提供了HTTP特殊字符转码

  1. String url = "http://127.0.0.1:8080/tranIndex?";
  2. // 参数转码
  3. String strParam = "name=" + URLEncoder.encode("1+1", "utf-8");
  4. String newUrl = url + strParam;
  5. String result = HttpClientUtils.httpGet(newUrl);
  6. System.out.println("result:" + result);

转码: URLEncoder.encode

解码: URLecoder.decoder

对称加密和非对称加密:

防止别人抓包分析HTTP请求 篡改数据

对称加密:

加密和解密都是同一个密钥。才加解密过程当中,使用同一个密钥。

1179709-20190125161553721-1941447836.png

客户端加密 服务器端解密 使用的是同一个密钥

抓包抓到的是 加密后的名问数据

对称加密: 加密解密都是同一个密钥。加密过程中,使用同一个密钥。

对称加密速度快

服务器端与服务器端进行通信(后台与后台通讯)

比如: 构建网站与机构网站进行合作的情况可以使用对称加密(同一个网段里面 抓包分析抓不到包)

密钥是长度8的倍数

密码不可能使用对称加密 别人可以反向获取 密码使用单向加密 不可以被逆向破解 密码使用MD5加密 再加盐

信息加密与密钥管理

单向散列加密

散列是信息的提炼,通常其长度要比信息小得多,且为一个固定长度。加密性强的散列一定是不可逆的,这就意味着通过散列结果,无法推出任何部分的原始信息。任何输入信息的变化,哪怕仅一位,都将导致散列结果的明显变化,这称之为雪崩效应。散列还应该是防冲突的,即找不出具有相同散列结果的两条信息。具有这些特性的散列结果就可以用于验证信息是否被修改。
单向散列函数一般用于产生消息摘要,密钥加密等,常见的有:
1、MD5(Message Digest Algorithm 5):是RSA数据安全公司开发的一种单向散列算法,非可逆,相同的明文产生相同的密文。
2、SHA(Secure Hash Algorithm):可以对任意长度的数据运算生成一个160位的数值;
SHA-1与MD5的比较
因为二者均由MD4导出,SHA-1和MD5彼此很相似。相应的,他们的强度和其他特性也是相似,但还有以下几点不同:
1、对强行供给的安全性:最显著和最重要的区别是SHA-1摘要比MD5摘要长32 位。使用强行技术,产生任何一个报文使其摘要等于给定报摘要的难度对MD5是2128数量级的操作,而对SHA-1则是2160数量级的操作。这样,SHA-1对强行攻击有更大的强度。
2、对密码分析的安全性:由于MD5的设计,易受密码分析的攻击,SHA-1显得不易受这样的攻击。
3、速度:在相同的硬件上,SHA-1的运行速度比MD5慢。

1、特征:雪崩效应、定长输出和不可逆。
2、作用是:确保数据的完整性。
3、加密算法:md5(标准密钥长度128位)、sha1(标准密钥长度160位)、md4、CRC-32
4、加密工具:md5sum、sha1sum、openssl dgst。
5、计算某个文件的hash值,例如:md5sum/shalsum FileName,openssl dgst –md5/-sha

MD5加密

在线MD5解密与加密

http://www.cmd5.com/

Java操作MD5加密
MD5加盐实现方式

一般使用的加盐:

md5(Password+UserName),即将用户名和密码字符串相加再MD5,这样的MD5摘要基本上不可反查。

但有时候用户名可能会发生变化,发生变化后密码即不可用了(验证密码实际上就是再次计算摘要的过程)。

-————-

因此我们做了一个非常简单的加盐算法,每次保存密码到数据库时,都生成一个随机16位数字,将这16位数字和密码相加再求MD5摘要,然后在摘要中再将这16位数字按规则掺入形成一个48位的字符串。

在验证密码时再从48位字符串中按规则提取16位数字,和用户输入的密码相加再MD5。按照这种方法形成的结果肯定是不可直接反查的,且同一个密码每次保存时形成的摘要也都是不同的。

信息加密技术

对称加密

对称密码技术:发件人和收件人使用其共同拥有的单个密钥 ,这种密钥既用于加密,也用于解密,叫做机密密钥(也称为对称密钥或会话密钥)。

  1. 能够提供信息机密性(没有密钥信息不能被解密)、完整性(被改变的信息不能被解密)的服务。
  2. 对称式密码学又称:单钥密码学、秘密密钥密码学、会话密钥密码学、私钥密码学、共享秘钥密码学
常见的对称式加密技术

DES(数据加密标准):分组式加密,算法源于Lucifer,作为NIST对称式加密标准;64位(有效位56位、校验8位),分组算法

3DES:128位,分组算法

  1. IDEA(国际数据加密算法):128位,比DES快,分组算法
  2. Blowfish32-448位,算法公开,分组算法
  3. RC4:流密码,密钥长度可变
  4. RC5:分组密码,密钥长度可变,最大2048
  5. Rijndael128位/196位/256
  6. AES(高级加密标准):DES升级版,算法出自Rinjindael
对称密码的优点

用户只需记忆一个密钥,就可用于加密、解密;

与非对称加密方法相比,加密解密的计算量小,速度快,简单易用,适合于对海量数据进行加密处理 。

对称密码的缺点

如果密钥交换不安全,密钥的安全性就会丧失。特别是在电子商务环境下,当客户是未知的、不可信的实体时,如何使客户安全地获得密钥就成为一大难题。

  1. 如果用户较多情况下的密钥管理问题。N\*(N-1)/2
  2. 如果密钥多个用户被共享,不能提供抗抵赖性
对称密码案例

假设Alice和Bob是认识的,两人为了保证通信消息不被其它人截取,预先约定了一个密码,用来加密在他们之间传送的消息,这样即使有人截取了消息没有密码也无法知道消息的内容。由此便实现了机密性

1179709-20190125163213109-1997476568.png

基于DES实现加密和解密
DES加密工具类

DES加密介绍 DES是一种对称加密算法,所谓对称加密算法即:加密和解密使用相同密钥的算法。DES加密算法出自IBM的研究,后来被美国政府正式采用,之后开始广泛流传,但是近些年使用越来越少,因为DES使用56位密钥,以现代计算能力,24小时内即可被破解。虽然如此,在某些简单应用中,我们还是可以使用DES加密算法,本文简单讲解DES的JAVA实现 。注意:DES加密和解密过程中,密钥长度都必须是8的倍数

保证密钥相同

  1. public static void main(String args[]) {
  2. // 待加密内容
  3. String str = "cryptology";
  4. // 密码,长度要是8的倍数
  5. String password = "95880288";
  6. byte[] result = DES.encrypt(str.getBytes(), password);
  7. System.out.println("加密后:" + new String(result));
  8. // 直接将如上内容解密
  9. try {
  10. byte[] decryResult = DES.decrypt(result, password);
  11. System.out.println("解密后:" + new String(decryResult));
  12. } catch (Exception e1) {
  13. e1.printStackTrace();
  14. }
  15. }

对称加密优缺点:

反编译出密钥来 就完蛋了 同一个密钥

对称加密的使用场景 服务器端与服务器端进行加密 比较好一些 没法用抓包

非对称加密

使用一对密钥:一个用于加密信息,另一个则用于解密信息。

  1. 两个密钥之间存在着相互依存关系:即用其中任一个密钥加密的信息只能用另一个密钥进行解密。
  2. 其中加密密钥不同于解密密钥,公钥加密私钥解密,反之也可私钥加密公钥解密。
  3. 密钥依据性质划分,将其中的一个向外界公开,称为公钥;另一个则自己保留,称为私钥。公钥(Public key)常用于数据加密(用对方公钥加密)或签名验证(用对方公钥解密),私钥(Private key)常用于数据解密(发送方用接收方公钥加密)或数字签名(用自己私钥加密)。
  4. 机密性、完整性、抗抵赖性

1179709-20190125182508372-346362562.png

1.使用过程:

乙方生成两把密钥(公钥和私钥)

甲方获取乙方的公钥,然后用它对信息加密。

乙方得到加密后的信息,用私钥解密,乙方也可用私钥加密字符串

甲方获取乙方私钥加密数据,用公钥解密

优点:难破解

缺点: 加密速度慢

常用算法:

RSA、Elgamal、背包算法、Rabin、D-H、ECC(椭圆曲线加密算法)

移动APP接口安全 (HTTPs传输,使用令牌,使用非对称加密)

对称加密的话 对称加密情况下 密钥都是相同的 反编译移动打包apk

既然移动app端不能用对称加密,用非对称加密

非对称加密。 私钥(不公开)和公钥(公开)

首先非对称加密,是一对密钥(必须组合公钥和密钥进行组合)

1,使用第三方工具生成非对称加密

2,如果使用公钥加密,必须使用私钥解密

  1. 如果使用私钥加密, 那么必须要使用公钥解密。
  2. 安全但是效率低,应用场景: 支付宝 第三方支付对接

1179709-20190125183935589-1556572847.png

移动APP 服务器端

公钥加密 私钥解密!

移动App端使用公钥加密 移动app客户端保存公钥 app使用公钥加密 服务器端保存私钥 服务器端使用私钥进行保密 私钥在服务器端很给力的 黑客获取不到

app和服务器 有个约定 生成一堆非对称密钥对 服务器端保存私钥 客户端保存公钥

公钥A 私钥B

公钥1 公钥2

必须成对的才可以解密!

RSA加密:

实际过程中,开发人员先把公钥私钥生成好。服务器端保存私钥,公钥发给客户端。

生成公钥和私:

  1. /**
  2. * 生成公钥和私钥
  3. */
  4. public static void generateKey() {
  5. // 1.初始化秘钥
  6. KeyPairGenerator keyPairGenerator;
  7. try {
  8. keyPairGenerator = KeyPairGenerator.getInstance("RSA");
  9. SecureRandom sr = new SecureRandom(); // 随机数生成器
  10. keyPairGenerator.initialize(512, sr); // 设置512位长的秘钥
  11. KeyPair keyPair = keyPairGenerator.generateKeyPair(); // 开始创建
  12. RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
  13. RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
  14. // 进行转码
  15. publicKey = Base64.encodeBase64String(rsaPublicKey.getEncoded());
  16. // 进行转码
  17. privateKey = Base64.encodeBase64String(rsaPrivateKey.getEncoded());
  18. } catch (NoSuchAlgorithmException e) {
  19. // TODO Auto-generated catch block
  20. e.printStackTrace();
  21. }
  22. }

测试:

  1. import javax.crypto.Cipher;
  2. public class Test001 {
  3. public static void main(String[] args) {
  4. // 实现步骤:
  5. // 1.生成公钥和私钥密钥对
  6. RSAUtil.generateKey();
  7. System.out.println("私钥:" + RSAUtil.privateKey);
  8. System.out.println("公钥:" + RSAUtil.publicKey);
  9. String content = "toov5comeon";
  10. System.out.println("加密前:"+content);
  11. // 2.使用公钥进行加密
  12. String encryptByPublicKey = RSAUtil.encryptByPublicKey(content, RSAUtil.publicKey, Cipher.ENCRYPT_MODE); //最后一个参数表示进行加密 返回加密后的结果
  13. System.out.println("加密后:" + encryptByPublicKey);
  14. String encryptByprivateKey = RSAUtil.encryptByprivateKey(encryptByPublicKey, RSAUtil.privateKey,
  15. Cipher.DECRYPT_MODE);
  16. // 3.使用私钥进行解密
  17. System.out.println("解密后:" + encryptByprivateKey);
  18. // 正常在开发中的时候,后端开发人员生成好密钥对,服务器端保存私钥 客户端保存公钥
  19. }
  20. }

1179709-20190125185938902-1093922011.png

注意了 这可是有加号的 在RPC远程调用时候 可能这种特殊字符会被转换了哦 特殊字符处理

防止抓包篡改数据:

基于令牌的方式实现参数安全传输:

A (主站) B(支付)

在跳转支付系统之前生成参数令牌

A调用B 支付系统生成令牌参数,返回参数令牌。

A跳转到B使用令牌方式跳转

支付系统接收令牌参数获取对应的userId和全额参数

访问时候,携带moeny userId ,服务器获取到然后生成token,并存入到redis(实际是存在数据库中) 中 key为token value为money userId

调用支付时候 携带 token,服务器端通过token去查询出money userid 进行操作

核心代码:

  1. import java.util.UUID;
  2. import org.apache.commons.lang.StringUtils;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.web.bind.annotation.RequestMapping;
  5. import org.springframework.web.bind.annotation.RestController;
  6. import com.fasterxml.jackson.databind.deser.Deserializers.Base;
  7. import com.itmayiedu.base.BaseApiService;
  8. import com.itmayiedu.base.BaseRedisService;
  9. import com.itmayiedu.base.ResponseBase;
  10. @RestController
  11. public class PayController extends BaseApiService {
  12. @Autowired
  13. private BaseRedisService baseRedisService;
  14. private static final Long TOKENTIME = (long) (30 * 60);
  15. // 先获取参数接口,返回令牌
  16. // 使用令牌传递参数 (不是前端调用是服务器调用)
  17. @RequestMapping("/getPayToken")
  18. public String getPayToken(Long userId, Long money) {
  19. // 生成令牌 令牌是随便生成的
  20. String payToken = UUID.randomUUID().toString();
  21. // 存放在redis中
  22. baseRedisService.setString(payToken, userId + "---" + money, TOKENTIME);
  23. return payToken;
  24. }
  25. @RequestMapping("/pay")
  26. public ResponseBase pay(String payToken) { //进行支付时候 就传递上次生成的token就好了
  27. if (StringUtils.isEmpty(payToken)) {
  28. return setResultError("token 不能为空!");
  29. }
  30. String result = (String) baseRedisService.getString(payToken);
  31. if (StringUtils.isEmpty(result)) {
  32. return setResultError("参数不能为空!");
  33. }
  34. // 直接处理操作数据库
  35. return setResultSuccessData(result);
  36. }
  37. }

辅助代码:

Base:

  1. import org.springframework.stereotype.Component;
  2. import com.itmayiedu.utils.Constants;
  3. @Component
  4. public class BaseApiService {
  5. public ResponseBase setResultError(Integer code, String msg) {
  6. return setResult(code, msg, null);
  7. }
  8. // 返回错误,可以传msg
  9. public ResponseBase setResultError(String msg) {
  10. return setResult(Constants.HTTP_RES_CODE_500, msg, null);
  11. }
  12. // 返回成功,可以传data值
  13. public ResponseBase setResultSuccessData(Object data) {
  14. return setResult(Constants.HTTP_RES_CODE_200, Constants.HTTP_RES_CODE_200_VALUE, data);
  15. }
  16. public ResponseBase setResultSuccessData(Integer code, Object data) {
  17. return setResult(code, Constants.HTTP_RES_CODE_200_VALUE, data);
  18. }
  19. // 返回成功,沒有data值
  20. public ResponseBase setResultSuccess() {
  21. return setResult(Constants.HTTP_RES_CODE_200, Constants.HTTP_RES_CODE_200_VALUE, null);
  22. }
  23. // 返回成功,沒有data值
  24. public ResponseBase setResultSuccess(String msg) {
  25. return setResult(Constants.HTTP_RES_CODE_200, msg, null);
  26. }
  27. // 通用封装
  28. public ResponseBase setResult(Integer code, String msg, Object data) {
  29. return new ResponseBase(code, msg, data);
  30. }
  31. }

redis:

  1. import java.util.concurrent.TimeUnit;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.data.redis.core.StringRedisTemplate;
  4. import org.springframework.stereotype.Component;
  5. @Component
  6. public class BaseRedisService {
  7. @Autowired
  8. private StringRedisTemplate stringRedisTemplate;
  9. public void setString(String key, Object data, Long timeout) {
  10. if (data instanceof String) {
  11. String value = (String) data;
  12. stringRedisTemplate.opsForValue().set(key, value);
  13. }
  14. if (timeout != null) {
  15. stringRedisTemplate.expire(key, timeout, TimeUnit.SECONDS);
  16. }
  17. }
  18. public Object getString(String key) {
  19. return stringRedisTemplate.opsForValue().get(key);
  20. }
  21. public void delKey(String key) {
  22. stringRedisTemplate.delete(key);
  23. }
  24. }

response:

  1. import lombok.Getter;
  2. import lombok.Setter;
  3. import lombok.extern.slf4j.Slf4j;
  4. @Getter
  5. @Setter
  6. @Slf4j
  7. public class ResponseBase {
  8. private Integer rtnCode;
  9. private String msg;
  10. private Object data;
  11. public ResponseBase() {
  12. }
  13. public ResponseBase(Integer rtnCode, String msg, Object data) {
  14. super();
  15. this.rtnCode = rtnCode;
  16. this.msg = msg;
  17. this.data = data;
  18. }
  19. public static void main(String[] args) {
  20. ResponseBase responseBase = new ResponseBase();
  21. responseBase.setData("123456");
  22. responseBase.setMsg("success");
  23. responseBase.setRtnCode(200);
  24. System.out.println(responseBase.toString());
  25. log.info("itmayiedu...");
  26. }
  27. @Override
  28. public String toString() {
  29. return "ResponseBase [rtnCode=" + rtnCode + ", msg=" + msg + ", data=" + data + "]";
  30. }
  31. }

posted @ 2019-01-25 19:42 toov5 阅读( …) 评论( …) 编辑 收藏

发表评论

表情:
评论列表 (有 0 条评论,596人围观)

还没有评论,来说两句吧...

相关阅读

    相关 加密算法-对称加密&对称加密

    加密算法是一种将明文转换为密文的算法,以保护数据的机密性和安全性。加密算法通常分为两种类型:对称加密算法和非对称加密算法。 1. 对称加密算法:指加密和解密使用相同密钥的算

    相关 对称加密对称加密

    1.明文 明文指的是未被加密过的原始数据。 2.密文 明文被某种加密算法加密之后,会变成密文,从而确保原始数据的安全。 密文也可以被解密,得到原

    相关 对称加密对称加密

    对称加密与非对称加密 对称加密算法 简介 > 加密和解密用到的密钥是相同的,这种加密方式加密速度非常快,适合经常发送数据的场合。缺点是密钥的传输比较麻烦。常

    相关 对称加密对称加密

    非对称加密和对称加密在加密和解密过程、加密解密速度、传输的安全性上都有所不同,具体介绍如下: 1、加密和解密过程不同 对称加密过程和解密过程使用的同一个密钥,加密过程相当于