API安全之 - 对称加密,非对称加密,令牌加密

为什么要加密?

api 接口不加密,就等于裸奔,参数信息f12 就能被获取
抓包工具甚至直接可以篡改参数,如:买一个商品金额参数为999,直接篡改为0.01,自己想想吧

一、对称加密

1、对称密码技术描叙

1、发件人和收件人使用其共同拥有的单个密钥 ,这种密钥既用于加密,也用于解密,叫做机密密钥(也称为对称密钥或会话密钥)。
2、 能够提供信息机密性(没有密钥信息不能被解密)、完整性(被改变的信息不能被解密)的服务。
3、对称式密码学又称:单钥密码学、秘密密钥密码学、会话密钥密码学、私钥密码学、共享秘钥密码学
如下:
假设Alice和Bob是认识的,两人为了保证通信消息不被其它人截取,预先约定了一个密码,用来加密在他们之间传送的消息,这样即使有人截取了消息没有密码也无法知道消息的内容。由此便实现了机密性。
在这里插入图片描述

2、对称密码的优点

1、 用户只需记忆一个密钥,就可用于加密、解密;
2、 与非对称加密方法相比,加密解密的计算量小,速度快,简单易用,适合于对海量数据进行加密处理 。

3、对称密码的缺点

1、如果密钥交换不安全,密钥的安全性就会丧失。特别是在电子商务环境下,当客户是未知的、不可信的实体时,如何使客户安全地获得密钥就成为一大难题。
2、如果用户较多情况下的密钥管理问题。N*(N-1)/2
3、如果密钥多个用户被共享,不能提供抗抵赖性

4、对称加密方案

DES(数据加密标准):分组式加密,算法源于Lucifer,作为NIST对称式加密标准;64位(有效位56位、校验8位),分组算法
AES(高级加密标准):DES升级版,算法出自Rinjindael
3DES:128位,分组算法
IDEA(国际数据加密算法):128位,比DES快,分组算法
Blowfish:32-448位,算法公开,分组算法
RC4:流密码,密钥长度可变
RC5:分组密码,密钥长度可变,最大2048位
Rijndael:128位/196位/256位

5、对称加密方案之 DES 加解密工具类

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

	/**
	 * 加密
	 * 
	 * @param datasource
	 *            byte[]
	 * @param password
	 *            String
	 * @return byte[]
	 */
	public static byte[] encrypt(byte[] datasource, String password) {
		try {
			SecureRandom random = new SecureRandom();
			DESKeySpec desKey = new DESKeySpec(password.getBytes());
			// 创建一个密匙工厂,然后用它把DESKeySpec转换成
			SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
			SecretKey securekey = keyFactory.generateSecret(desKey);
			// Cipher对象实际完成加密操作
			Cipher cipher = Cipher.getInstance("DES");
			// 用密匙初始化Cipher对象,ENCRYPT_MODE用于将 Cipher 初始化为加密模式的常量
			cipher.init(Cipher.ENCRYPT_MODE, securekey, random);
			// 现在,获取数据并加密
			// 正式执行加密操作
			return cipher.doFinal(datasource); // 按单部分操作加密或解密数据,或者结束一个多部分操作
		} catch (Throwable e) {
			e.printStackTrace();
		}
		return null;
	}


	/**
	 * 解密
	 * 
	 * @param src
	 *            byte[]
	 * @param password
	 *            String
	 * @return byte[]
	 * @throws Exception
	 */
	public static byte[] decrypt(byte[] src, String password) throws Exception {
		// DES算法要求有一个可信任的随机数源
		SecureRandom random = new SecureRandom();
		// 创建一个DESKeySpec对象
		DESKeySpec desKey = new DESKeySpec(password.getBytes());
		// 创建一个密匙工厂
		SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");// 返回实现指定转换的
																			// Cipher
																			// 对象
		// 将DESKeySpec对象转换成SecretKey对象
		SecretKey securekey = keyFactory.generateSecret(desKey);
		// Cipher对象实际完成解密操作
		Cipher cipher = Cipher.getInstance("DES");
		// 用密匙初始化Cipher对象
		cipher.init(Cipher.DECRYPT_MODE, securekey, random);
		// 真正开始解密操作
		return cipher.doFinal(src);
	}
}

6、测试 DES 加解密

	// 测试
	public static void main(String args[]) {
		// 待加密内容
		String str = "cryptology";
		// 密码,长度要是8的倍数
		String password = "95880288";

		byte[] result = DES.encrypt(str.getBytes(), password);
		System.out.println("加密后:" + new String(result));
		// 直接将如上内容解密
		try {
			byte[] decryResult = DES.decrypt(result, password);
			System.out.println("解密后:" + new String(decryResult));
		} catch (Exception e1) {
			e1.printStackTrace();
		}
	}

二、非对称加密

1、描叙

公钥和私钥是一对
1、使用公钥加密,那么就要使用私钥解密 ( 推荐使用公钥加密,私钥解密)
2、使用私钥加密,那么就要使用公钥解密
在这里插入图片描述

2、使用过程:

这里乙方可以理解为后端,甲方可以理解为前端,前后端进行数据传递时加解密操作

1、乙方生成两把密钥(公钥和私钥)
2、甲方获取乙方的公钥,然后用它对信息加密。
3、乙方得到加密后的信息,用私钥解密,乙方也可用私钥加密字符串
4、甲方获取乙方私钥加密数据,用公钥解密

优点: 难破解
缺点 :加密速度慢

3、非对称加密方案之 RSA 工具类

/**
 * RSA加解密工具类
 * 
 * @author QiuFeihu
 *
 */
public class RSAUtil {

	public static String publicKey; // 公钥
	public static String privateKey; // 私钥

	/**
	 * 生成公钥和私钥
	 */
	public static void generateKey() {
		// 1.初始化秘钥
		KeyPairGenerator keyPairGenerator;
		try {
			keyPairGenerator = KeyPairGenerator.getInstance("RSA");
			SecureRandom sr = new SecureRandom(); // 随机数生成器
			keyPairGenerator.initialize(512, sr); // 设置512位长的秘钥
			KeyPair keyPair = keyPairGenerator.generateKeyPair(); // 开始创建
			RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
			RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
			// 进行转码
			publicKey = Base64.encodeBase64String(rsaPublicKey.getEncoded());
			// 进行转码
			privateKey = Base64.encodeBase64String(rsaPrivateKey.getEncoded());
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * 私钥匙加密或解密
	 * 
	 * @param content
	 * @param privateKeyStr
	 * @return
	 */
	public static String encryptByprivateKey(String content, String privateKeyStr, int opmode) {
		// 私钥要用PKCS8进行处理
		PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyStr));
		KeyFactory keyFactory;
		PrivateKey privateKey;
		Cipher cipher;
		byte[] result;
		String text = null;
		try {
			keyFactory = KeyFactory.getInstance("RSA");
			// 还原Key对象
			privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
			cipher = Cipher.getInstance("RSA");
			cipher.init(opmode, privateKey);
			if (opmode == Cipher.ENCRYPT_MODE) { // 加密
				result = cipher.doFinal(content.getBytes());
				text = Base64.encodeBase64String(result);
			} else if (opmode == Cipher.DECRYPT_MODE) { // 解密
				result = cipher.doFinal(Base64.decodeBase64(content));
				text = new String(result, "UTF-8");
			}

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return text;
	}

	/**
	 * 公钥匙加密或解密
	 * 
	 * @param content
	 * @param privateKeyStr
	 * @return
	 */
	public static String encryptByPublicKey(String content, String publicKeyStr, int opmode) {
		// 公钥要用X509进行处理
		X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyStr));
		KeyFactory keyFactory;
		PublicKey publicKey;
		Cipher cipher;
		byte[] result;
		String text = null;
		try {
			keyFactory = KeyFactory.getInstance("RSA");
			// 还原Key对象
			publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
			cipher = Cipher.getInstance("RSA");
			cipher.init(opmode, publicKey);
			if (opmode == Cipher.ENCRYPT_MODE) { // 加密
				result = cipher.doFinal(content.getBytes());
				text = Base64.encodeBase64String(result);
			} else if (opmode == Cipher.DECRYPT_MODE) { // 解密
				result = cipher.doFinal(Base64.decodeBase64(content));
				text = new String(result, "UTF-8");
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return text;
	}



}

4、测试方法

	// 测试方法
	public static void main(String[] args) {
		/**
		 * 注意: 私钥加密必须公钥解密 公钥加密必须私钥解密
		 */
		System.out.println("-------------生成两对秘钥,分别发送方和接收方保管-------------");
		RSAUtil.generateKey();
		System.out.println("公钥匙给接收方:" + RSAUtil.publicKey);
		System.out.println("私钥给发送方:" + RSAUtil.privateKey);

		System.out.println("-------------第一个栗子,私钥加密公钥解密-------------");
		// String textsr = "早啊,你吃早饭了吗?O(∩_∩)O~";
		// // 私钥加密
		// String cipherText = RSAUtil.encryptByprivateKey(textsr,
		// RSAUtil.privateKey, Cipher.ENCRYPT_MODE);
		// System.out.println("发送方用私钥加密后:" + cipherText);
		// // 公钥解密
		// String text = RSAUtil.encryptByPublicKey(cipherText,
		// RSAUtil.publicKey, Cipher.DECRYPT_MODE);
		// System.out.println("接收方用公钥解密后:" + text);

		System.out.println("-------------第二个栗子,公钥加密私钥解密-------------");
		// 公钥加密
		String textsr = "吃过啦!你吃了吗?O(∩_∩)O~";

		String cipherText = RSAUtil.encryptByPublicKey(textsr, RSAUtil.publicKey, Cipher.ENCRYPT_MODE);
		System.out.println("接收方用公钥加密后:" + cipherText);
		// 私钥解密
		String text = RSAUtil.encryptByprivateKey(cipherText, RSAUtil.privateKey, Cipher.DECRYPT_MODE);
		System.out.print("发送方用私钥解密后:" + text);
	}

三、令牌加密(Toket)

a 系统进行页面跳转到 b系统,并携带相关参数信息
如:
联合登录
分布式系统中商品展示,下单是两个系统,下单需要把商品金额和商品信息传递给另一个系统进行页面展示

这个时候我们可以使用令牌加密,

1、过程

假如现在 a 系统页面,要跳转到b 系统页面并携带参数,这个时候不能再直接把参数直接在页面传递吗,会被抓包工具抓到
1、 a 系统请求后台接口,后台接口使用 HttpClient 发送参数给b 系统 ,b 系统保存参数并生成令牌
2、b 系统返回 toket 令牌
3、a 系统页面跳转b 系统访问b 系统接口时携带 toket 令牌,b 系统通过 toket 令牌获取相关参数

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JWT(JSON Web Token)是一种用于在网络应用间安全传输信息的开放标准。JWT 由三部分组成:头部(header)、载荷(payload)和签名(signature)。 在 JWT 中,使用非对称加密算法来实现签名验证。非对称加密算法使用了一对密钥,包括私钥和公钥。私钥用于生成签名,公钥用于验证签名的有效性。 下面是 JWT 的非对称加密原理: 1. 客户端发送请求时,服务器返回一个 JWT。 2. JWT 由三部分组成,分别是头部、载荷和签名,它们通过点号(.)连接在一起。 3. 头部包含算法类型和令牌类型等信息,例如: ``` { "alg": "RS256", "typ": "JWT" } ``` 4. 载荷包含要传输的数据,例如用户的身份信息,例如: ``` { "sub": "1234567890", "name": "John Doe", "iat": 1516239022 } ``` 5. 签名是由头部、载荷和私钥生成的,例如: ``` HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secretKey ) ``` 或者使用非对称加密算法生成签名: ``` RSASHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), privateKey ) ``` 6. 客户端将生成的 JWT 发送给服务器作为身份认证凭证。 7. 服务器接收到 JWT 后,通过公钥来验证签名的有效性,确保 JWT 的完整性和真实性。 8. 如果签名验证通过,服务器使用私钥对 JWT 进行解密,获取其中的信息。 通过使用非对称加密算法和私钥签名,JWT 实现了身份验证和信息传输的安全性。在验证签名时,服务器可以根据公钥来验证,而不需要直接访问私钥。这种方式可以确保 JWT 的安全性,并防止篡改和伪造。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值