目录

  • 背景
  • AES CBC 加解密算法
  • 代码实现
    • Java 生成 key 和 iv
    • Java 加密 & 解密
    • JavaScript 解密
  • 小结

背景

我们的游戏充值平台马上要到货一批充值码,需要入库。之前充值码发奖相关的需求都是我做的,但在存储充值码的时候没有加密,是明文存储的。

现在的需求是,数据库中的充值码需要密文存储。这就涉及到:

  • 提供一个新增充值码记录的接口,请求参数为明文,使用 Java 加密后把充值码密文存入数据库;
  • 发送充值码邮件时,需要使用 Java 解密充值码,给用户发送明文;
  • 前端展示充值码时,服务端传送密文,前端使用 JavaScript 解密,给用户展示明文;(纯属多此一举,因为 HTTPS 通信本来就是加密的。但业务方坚持要这样做。)

AES CBC 加解密算法

这是我第一次做加密相关的需求。一开始(几周前吧)图省事,想着在 StackOverflow 上搜一下,一两行代码就搞定了,不就是个加密嘛。后来发现,怎么都这么复杂啊,一直搜到我身心俱疲,也没找到简单的方法。

这回我静下心来,好好读了一篇介绍 AES 的文章,终于大体上搞明白了。

参考链接:Java AES Encryption and Decryption

简单来说就是,AES 分为很多模式,但大家基本上都用 CBC。

在 CBC 模式下,除了秘钥 key 之外,为了增强安全性,还需要一个 iv。(最基础的 ECB 模式不需要 iv,只需要 key,但该模式不提倡使用)。

key 有 128、192、256 位三种选择,iv 固定是 128 位,因为加密块固定是 128 位,需要加密的信息需要先分成 128 位大小的块,如果最后一块不足 128 位需要填充到 128 位(padding)。实际上并不需要用户自己填充,指定参数就行。

代码实现

Java 生成 key 和 iv

生成一个新的 key(默认 128 位):

public static SecretKey generateKey(int n) throws NoSuchAlgorithmException {KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");keyGenerator.init(n);SecretKey key = keyGenerator.generateKey();return key;
}

生成一个新的 iv

public static IvParameterSpec generateIv() {byte[] iv = new byte[16];new SecureRandom().nextBytes(iv);return new IvParameterSpec(iv);
}

当然,生成之后最终是要用字符串的格式保存和传送 keyiv 的。下面使用 base64 格式保存:

// 使用上面的方法生成 key 并转换为 base64 格式
SecretKey key = EncryptUtils.generateKey(128);
String keyBase64 = Base64.getEncoder().encodeToString(key.getEncoded());// 使用上面的方法生成 iv 并转换为 base64 格式
IvParameterSpec ivParameterSpec = EncryptUtils.generateIv();
String ivBase64 = Base64.getEncoder().encodeToString(ivParameterSpec.getIV());

Java 加密 & 解密

首先,可以把 base64 格式的 keyiv 转换回 Java 中的类型(参考链接:Converting Secret Key into a String and Vice Versa)

代码如下:

// 导入 key
byte[] keyBytes = Base64.getDecoder().decode(keyBase64);
SecretKey key = new SecretKeySpec(keyBytes, 0, keyBytes.length, "AES");// 导入 iv
byte[] ivBytes = Base64.getDecoder().decode(ivBase64);
IvParameterSpec iv = new IvParameterSpec(ivBytes);

之后就是用 keyiv 来进行加密和解密了:

String algorithm = "AES/CBC/PKCS5Padding";// 加密,input 是要加密的明文,返回的是一个 base64 格式的密文:
public static String encrypt(String algorithm, String input, SecretKey key,IvParameterSpec iv) throws NoSuchPaddingException, NoSuchAlgorithmException,InvalidAlgorithmParameterException, InvalidKeyException,BadPaddingException, IllegalBlockSizeException {Cipher cipher = Cipher.getInstance(algorithm);cipher.init(Cipher.ENCRYPT_MODE, key, iv);byte[] cipherText = cipher.doFinal(input.getBytes());return Base64.getEncoder().encodeToString(cipherText);
}// 解密,cipherText 是 base64格式的密文
public static String decrypt(String algorithm, String cipherText, SecretKey key,IvParameterSpec iv) throws NoSuchPaddingException, NoSuchAlgorithmException,InvalidAlgorithmParameterException, InvalidKeyException,BadPaddingException, IllegalBlockSizeException {Cipher cipher = Cipher.getInstance(algorithm);cipher.init(Cipher.DECRYPT_MODE, key, iv);byte[] plainText = cipher.doFinal(Base64.getDecoder().decode(cipherText));return new String(plainText);
}

当然,实际使用时还是会做一些封装什么的,比如我把 cipher 单独存起来了。但大体就是这样了。

JavaScript 解密

JS 这边使用 CryptoJS 这个库来解密。

我没找到介绍 JS AES 加解密的特别好的文章,CryptoJS 的文档我感觉写的也不是很好。后来一路磕磕绊绊,看了好多个 StackOverflow 和 JSFiddle 之类的,花了得有俩小时,终于找到了解密方法:

参考链接:AES encryption using Java and decryption using Javascript

// 从 base64 格式导入 key 和 iv
var key = CryptoJS.enc.Base64.parse('nlCdv7/wqRIsf1iWzqz96Q==');
var iv = CryptoJS.enc.Base64.parse('n9CvQB/1quXtItsdhnel2g==');function decrypt(encrypted) {var cipherParams = CryptoJS.lib.CipherParams.create({// 从 base64 格式导入密文ciphertext: CryptoJS.enc.Base64.parse(encrypted)});// 解密return CryptoJS.AES.decrypt(cipherParams, key, {iv: iv,padding: CryptoJS.pad.Pkcs7,mode: CryptoJS.mode.CBC}).toString(CryptoJS.enc.Utf8);
}

小结

用 Java 进行 AES CBC 加密/解密还是比较简单的,之前只因我太急躁,错误地留下了“这件事很难”的印象。

先把加密的基本原理和流程搞清楚,再做就好多了。

【AES 算法】实现服务端 Java 加密,前端 JS 解密相关推荐

  1. 浅谈客户端与服务端的加密通讯(HTTPS/AES/RSA/RequestBodyAdviceAdapter/ResponseBodyAdvice)

    目录 前言 HTTPS与SSL证书 AES对称加密 RSA非对称加密 AES + RSA 组合加密 服务端请求参数解密拦截器RequestBodyAdviceAdapter 服务端返回参数加密拦截器R ...

  2. 客户端JavaScript加密数据,服务端Java解密数据

    原文:http://blog.csdn.net/peterwanghao/article/details/43303807 在普通的页面提交时,如果没有使用SSL,提交的数据将使用纯文本的方式发送.如 ...

  3. 区块链教程Fabric1.0源代码分析流言算法Gossip服务端二

    区块链教程Fabric1.0源代码分析流言算法Gossip服务端二 Fabric 1.0源代码笔记 之 gossip(流言算法) #GossipServer(Gossip服务端) 5.2.commIm ...

  4. android binder - 客户端(c++层) 调用 服务端(java层),服务端回调客户端 例子

    学习了: android binder - 客户端(java层) 调用 服务端(c++层) 例子 http://blog.csdn.net/ganyue803/article/details/4131 ...

  5. gossip 区块链_区块链教程Fabric1.0源代码分析流言算法Gossip服务端一兄弟连区块链教程-阿里云开发者社区...

    区块链教程Fabric1.0源代码分析流言算法Gossip服务端一,2018年下半年,区块链行业正逐渐褪去发展之初的浮躁.回归理性,表面上看相关人才需求与身价似乎正在回落.但事实上,正是初期泡沫的渐退 ...

  6. java des加密与js解密

    java代码:import java.io.IOException; import java.security.SecureRandom;import javax.crypto.Cipher; imp ...

  7. jsp使用rsa加密服务端Java解密

    jsp 需要引入 jsencrypt.js 网站:https://www.bootcdn.cn/jsencrypt/ 可以进行获取下载 jsp代码 // 这里是从服务端获取的公钥 var public ...

  8. java websocket 实现_JAVA (Tomcat服务器)使用WebSocket实现服务端与HTML前端通信

    在一个项目中要使用WebSocket技术来实现服务器与浏览器实时通信交互,在网上也找了许多资料.为了防止以后忘记具体的使用过程,下面我把自己的使用过程和方法记录下来方便自己以后使用. 项目背景: 基于 ...

  9. 游戏社区App (三):客户端与服务端的加密处理 和 登录

    http请求数据无论是GET或者POST都可能会被抓包获取到数据.为了避免用户的敏感数据被窃取(比如密码),需要对数据进行加密处理. 一.相关名词解析 RSA:非对称加密. 会产生公钥和私钥,公钥在客 ...

最新文章

  1. 【Verilog HDL 训练】第 01 天
  2. python爬虫---从零开始(一)初识爬虫
  3. 关于外挂新手最常见的30个问题
  4. DeepFaceLab史上最快的环境搭建(虚拟环境)
  5. Apache与Tomcat使用
  6. linux usb 升级脚本,linux – 使用bash脚本更新CRON
  7. mysql naivcat执行存储过程_mysql使用navicat编写调用存储过程
  8. 验证必须是数字php,Element 中表单非必填数据项 必须为数字的验证问题
  9. 小米路由器dns辅服务器未响应,小米路由器频繁掉线的原因与解决办法
  10. 2021-10-07
  11. Django笔记:ORM模型
  12. ie版本过低提示升级ie的示例
  13. 计算机视觉之图像分割——Snake模型(1译文)
  14. arc093F Dark Horse
  15. cmake错误集锦:unkown arguments specified
  16. vue 记住密码下次自动登录
  17. 正则表达式(一)认识正则表达式
  18. POI-TL使用及工具类
  19. 【HCIA 03】华为静态路由配置
  20. 联想e480一键恢复小孔_联想自带一键恢复没用了怎么处理

热门文章

  1. Shader 材质BlenningPhong 代码模块
  2. U盘被删除的文件如何恢复?
  3. 痔疮后水肿该怎么办?
  4. C语言浮点数表示法 / float表示法(浮点数表示方法)
  5. Windows驱动学习(六)-- FSD钩子
  6. vueh5获取手机前置摄像头(安卓ios),input capture属性和navigator.mediaDevices
  7. 介词for和with 和of的用法_常用介词用法(for to with of)
  8. [嵌入式] 重温Mini2440(二)移植Linux-4.9.270
  9. ISO 光盘镜像 启动系统
  10. 国人被清朝误导300年