生成16位iv向量,使用该iv以及密钥加密原文
将加密后的真实密文与iv拼接: iv+真实密文
将与iv拼接后的密文用SHA-512 HMAC生成摘要信息(128位),与密文拼接: HMAC+base64后的密文,得到最终的密文
分离出hmac与密文,可以自行进行摘要检测,可以防止时序攻击.
得到拼接了iv的原文.分离出iv以及真实原文
使用密钥以及iv进行解码,得到原文
加密举例 php版本
/*****加密过程*****/
$str = "Hello World";
//1.使用16位密钥
$key = '12345678901234ab';
//2.生成16位iv 算法自定,示例中直接指定
//$iv = openssl_random_pseudo_bytes(16); //12345678ss1234ab
$iv="12345678ss1234ab";
//3.加密 IvdA7oP8BInWa5shY+LCyQ==
$secert_str = openssl_encrypt($str, 'AES-128-CBC', $key, 0, $iv);
$secert_str = $iv . $secert_str; //4.将iv与密文拼接 12345678ss1234abIvdA7oP8BInWa5shY+LCyQ==
//5.base64_encode 考虑语言兼容性问题,该步骤取消
//6.用SHA-512生成摘要 128位16进制 3b2106c05b46b603969c2b1bc7503c8233d209dcd204b098b33ba704507315480e03e499e0082e8842b60baa01f522d7c0342d75196d18d3514d37c58e31d733
$hmac = hash_hmac('sha512', $secert_str, $key, false);
//7.拼接摘要,得到密文
$secert_str = $hmac . $secert_str;
return urlencode($secert_str);
$str=rawurldecode($str);
$len = mb_strlen($secert_str);
$ori_hmac = substr($secert_str, 0, 128);
$data = substr($secert_str, 128, $len);
//2.验证摘要
$local_hmac = hash_hmac('sha512', $data, $key, false);
$diff = 0;
for ($i = 0; $i < 128; $i++) {
$diff |= ord($ori_hmac[$i]) ^ ord($local_hmac[$i]);
if ($diff !== 0) {
return FALSE;
//3.分离iv
$len = mb_strlen($data);
$iv = substr($data, 0, 16);
$data = substr($data, 16, $len);
//4.解密,获得原文
$data = openssl_decrypt($data, 'AES-128-CBC', $key, 0, $iv);
java加解密类
package main;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.Mac;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.util.encoders.Hex;
public class AESUtil {
* aes/128/cbc加密
* @param sSrc 明文
* @param sKey 密钥
* @param sIv 向量
* @return
* @throws Exception
public static String Encrypt(String sSrc, String sKey, String sIv) throws Exception {
if (sKey == null) {
System.out.print("Key为空null");
return null;
// 判断Key是否为16位
if (sKey.length() != 16) {
System.out.print("Key长度不是16位");
return null;
//1.加密
byte[] raw = sKey.getBytes();
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");//aes-cbc-pkcs5(pkcs5与pkcs7通用)
IvParameterSpec iv = new IvParameterSpec(sIv.getBytes());//使用CBC模式,需要一个向量iv,可增加加密算法的强度
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
byte[] encrypted = cipher.doFinal(sSrc.getBytes("UTF-8"));
String encryptedString = new String(Base64.encodeBase64(encrypted));
//2.拼接iv
encryptedString = sIv + encryptedString;
//3.sha512
String hmac = encodeHmacSHA512(encryptedString, sKey);
//4.拼接摘要
encryptedString = hmac+encryptedString;
//5.urlencode
encryptedString = URLEncoder.encode(encryptedString);
return encryptedString;
// 解密
* @param sSrc 密文
* @param sKey 密钥
* @return
* @throws Exception
public static String Decrypt(String sSrc, String sKey) throws Exception {
//0.urldecode
sSrc=URLDecoder.decode(sSrc);
//1.分离摘要
System.out.println(sSrc);
String hmac=sSrc.substring(0,128);
String data=sSrc.substring(128,sSrc.length());
//2.验证摘要
//3.分离iv
String sIv=data.substring(0,16);
String str=data.substring(16,data.length());
//4.解密
byte[] raw = sKey.getBytes("UTF-8");
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec iv = new IvParameterSpec(sIv.getBytes());
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
byte[] encrypted1 = Base64.decodeBase64(str.getBytes());
try {
byte[] original = cipher.doFinal(encrypted1);
String originalString = new String(original);
return originalString;
} catch (Exception e) {
System.out.println(e.toString());
return null;
}catch (Exception ex){
System.out.println(ex.toString());
return null;
* HmacSHA512消息摘要
* @param data 待做摘要处理的数据
* @param key 密钥
* @return
public static String encodeHmacSHA512(String data, String key) throws Exception {
byte[] bytesKey = key.getBytes();
SecretKeySpec secretKey = new SecretKeySpec(bytesKey, "HmacSHA512");
Mac mac = Mac.getInstance(secretKey.getAlgorithm());
mac.init(secretKey);
final byte[] macData = mac.doFinal(data.getBytes());
byte[] hex = new Hex().encode(macData);
String result = new String(hex, "ISO-8859-1");
return result;
java实例
import main.AESUtil;
public class Main {
public static void main(String[] args) {
//key
String cKey = "12345678901234ab";
// 需要加密的字串
String cSrc = "Hello World";
//iv 16位 算法自定 实例中直接指定
String sIv = "12345678ss1234ab";
String enString;
String deString;
try {
enString = AESUtil.Encrypt(cSrc, cKey, sIv);
System.out.println("加密后的字串是:" + enString);
deString = AESUtil.Decrypt("3b2106c05b46b603969c2b1bc7503c8233d209dcd204b098b33ba704507315480e03e499e0082e8842b60baa01f522d7c0342d75196d18d3514d37c58e31d73312345678ss1234abIvdA7oP8BInWa5shY+LCyQ==", cKey);
System.out.println("解密后的字串是:" + deString);
} catch (Exception e) {
e.printStackTrace();
AES
指高级
加密
标准(Advanced Encryption Standard),是当前最流行的一种密码算法,在web应用开发,特别是对外提供接口时经常会用到,下面是我整理的一套
php
与
java
通用的
AES
加密解密
算法。
php
版代码如下:
<?
php
class Crypt
AES
protected $cipher = MCRYPT_RIJNDAEL_12...
首先,通常情况下
Java
内部支持三种填充:NoPadding,PKCS5Padding(默认),ISO10126Padding。
如果选用NoPadding的话,对于数据长度不满16字节整数倍的情况下,
Java
是会报错的。
PHP
貌似是使用NoPadding填充,但实际上对于上述情况
PHP
内部是会以“\0”来填充,其实是一种Zero填充。
表现在
Java
中,则是由Bouncy Castle实...
这次在
JAVA
项目中遇到了要使用
PHP
的
openss
l_encrypt这个方法来
进行
加密
以下是内容分享:
在
PHP
中
加密
内容是:
//
openss
l_encrypt($data, $method, $password, $options, $
iv
)
openss
l_encrypt("6241378900148701870", 'des-ede3-cbc', 'f9b08f4...
PHP
与
JAVA
使用
AES
128位
加密
通信
问题:联调时候发现
php
的解密解析不了
java
加密
后的东西,解出来发现时乱码,当时就崩溃了,,奇了怪了,看了这篇文章,我真的是要醉了。。。。。。。。。。最后附上了
php
类库,留作以后备用。
问题:使用
Java
默认的
AES
加密
方式(Cipher.getInstance("
AES
"))并对
加密
后结果
进行
Base64编码,这样
php
(http:
在
PHP
和
Java
之间
进行
AES
加密
和解密时出现乱码问题,可能是因为两个语言
之间
使用了不同的编码方式。为了解决这个问题,我们需要在两个语言
之间
选择一种通用的编码方式,以确保
加密
和解密时的数据一致。
一种通用的编码方式是Base64编码。在
PHP
中,可以使用base64_encode()函数将
加密
后的数据转换为Base64编码。在
Java
中,可以使用
java
.util.Base64类
进行
编码和解码。在
进行
解密操作之前,需要先将Base64编码的数据解码成原始二进制数据。
下面是一个
PHP
和
Java
之间
进行
AES
加密
和解密的示例代码:
PHP
代码:
$key = 'your_key';
$data = 'your_data';
//
加密
$encrypted =
openss
l_encrypt($data, '
AES
-128-ECB', $key,
OPENSS
L_RAW_DATA);
$base64_encrypted = base64_encode($encrypted);
// 将
加密
后的数据传递给
Java
Java
代码:
import
java
.util.Base64;
import
java
x.crypto.Cipher;
import
java
x.crypto.spec.SecretKeySpec;
public class
AES
Utils {
pr
iv
ate static final String ALGO = "
AES
";
pr
iv
ate static final String MODE = "ECB";
pr
iv
ate static final String PADDING = "PKCS5Padding";
public static byte[] decrypt(byte[] key, byte[] encryptedData) throws Exception {
SecretKeySpec secretKeySpec = new SecretKeySpec(key, ALGO);
Cipher cipher = Cipher.getInstance(ALGO + "/" + MODE + "/" + PADDING);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
return cipher.doFinal(encryptedData);
public static void main(String[] args) throws Exception {
String keyStr = "your_key";
String encryptedStr = "your_base64_encrypted_data";
// 解码Base64编码的数据
byte[] encrypted = Base64.getDecoder().decode(encryptedStr);
byte[] key = keyStr.getBytes();
// 解密
byte[] decrypted =
AES
Utils.decrypt(key, encrypted);
String data = new String(decrypted);
System.out.println(data);
在上面的示例中,
PHP
代码将数据
加密
并转换为Base64编码,然后将其传递给
Java
代码。
Java
代码解码Base64编码的数据,使用
AES
算法
进行
解密,并将解密后的数据转换为字符串输出。注意,在实际应用中,需要确保
加密
和解密使用相同的密钥、算法、模式和填充方式。
呆呆树人:
轻松搞定 Nginx 跨域配置
陈*^_^*: