aardio 官方社区

 找回密码
 注册会员

QQ登录

只需一步,快速开始

搜索
查看: 13244|回复: 6

AES 加密算法多编程语言通用写法(aardio,PHP,C#,Java...)

[复制链接]

170

主题

2184

回帖

1万

积分

管理员

积分
13236
发表于 2017-11-15 19:55:23 | 显示全部楼层 |阅读模式
不同编程语言中AES加解密结果要保持一致要注意以下一些要点:
1、工作模式 CBC ,填充模式 PKCS7,不同语言要保持一致。
要注意 PKCS5 与 PKCS7 的填充规则是相同的,区别是PKCS5填充1到8字节,PKCS7填充1到255字节,而AES实际使用的数据区分组为 16 字节(128位),所以即使填充模式指定 PKCS5 - 实际使用的也是 PKCS7。下面的 JAVA代码里只能选 PKCS5 ,而 C#代码里只能选 PKCS7, 这都是兼容的没有问题。
2、在下面的示例中,加密向量统一设为与密钥相同。
3、不同编程语言使用的文本编码要一致,同一个字符串,使用UTF8或GBK编码在内存中存储的实际数据可能是不一样的。在aardio中默认编码为UTF-8,使用 string.fromto进行转换为其他编码。
4、如果加密后返回的密文用了BASE64或16进制编码,那么在解密时同样也先做对应的逆向解码。

先看 aardio 实现 AES 加密、解密的代码:
import console;  
import crypt.bin;
import crypt.aes;

//创建AES加密算法容器
var aes = crypt.aes();

//设置密钥(最大32个字节)
aes.setPassword("1234567812345678");

//不指定加密向量时默认设为密钥的值
//aes.setInitVector("1234567812345678")

//加密
var str = aes.encrypt("Test String");

//BASE64编码加密结果
console.log( crypt.bin.encodeBase64( str ) );

//解密
str = aes.decrypt(str);
console.log(str);

console.pause(
true);
  

170

主题

2184

回帖

1万

积分

管理员

积分
13236
 楼主| 发表于 2017-11-15 21:07:51 | 显示全部楼层
using System;
using System.Text;
using System.Security.Cryptography;

namespace TestApp
{
   
class Aes
    {
        static void Main(string[] args)
        {
            String str =
"Test String";
            String encryptData = Aes.Encrypt(str,
"1234567812345678", "1234567812345678");
            Console.WriteLine(encryptData);

            String dstr = Aes.Decrypt(
"xL1eEwu9WCDRiscUbPPPSA==", "1234567812345678", "1234567812345678");
            Console.WriteLine(dstr);
            Console.ReadKey();
        }

        public static string Encrypt(string toEncrypt, string key, string iv)
        {
            byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);
            byte[] ivArray = UTF8Encoding.UTF8.GetBytes(iv);
            byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);

            RijndaelManaged rm = new RijndaelManaged();
            rm.Key = keyArray;
            rm.IV = ivArray;
            rm.Mode = CipherMode.CBC;
            rm.Padding = PaddingMode.PKCS7;

            ICryptoTransform cTransform = rm.CreateEncryptor();
            byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
            
return Convert.ToBase64String(resultArray, 0, resultArray.Length);
        }

        public static string Decrypt(string toDecrypt, string key, string iv)
        {
            byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);
            byte[] ivArray = UTF8Encoding.UTF8.GetBytes(iv);
            byte[] toEncryptArray = Convert.FromBase64String(toDecrypt);

            RijndaelManaged rm = new RijndaelManaged();
            rm.Key = keyArray;
            rm.IV = ivArray;
            rm.Mode = CipherMode.CBC;
            rm.Padding = PaddingMode.PKCS7;

            ICryptoTransform cTransform = rm.CreateDecryptor();
            byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
            
return UTF8Encoding.UTF8.GetString(resultArray);
        }
    }
}

170

主题

2184

回帖

1万

积分

管理员

积分
13236
 楼主| 发表于 2017-11-15 23:00:24 | 显示全部楼层

import console;
import php;

php.code =
/***

//AES加密
function aes_encrypt($encryptKey,$encryptStr) {
    $localIV = $encryptKey;
    $encryptKey = $encryptKey;
   
    $module = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, $localIV);
    mcrypt_generic_init($module, $encryptKey, $localIV);
   
    $block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
    $pad = $block - (strlen($encryptStr) % $block);
    $encryptStr .= str_repeat(chr($pad), $pad);

    $encrypted = mcrypt_generic($module, $encryptStr);
    mcrypt_generic_deinit($module);
    mcrypt_module_close($module);

    return base64_encode($encrypted);

}

//AES解密
function aes_decrypt($encryptKey,$encryptStr) {
    $localIV = $encryptKey;
    $encryptKey = $encryptKey;

    $module = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, $localIV);
    mcrypt_generic_init($module, $encryptKey, $localIV);

    $encryptedData = base64_decode($encryptStr);
    $encryptedData = mdecrypt_generic($module, $encryptedData);
   
    $e = ord($encryptedData[strlen($encryptedData)-1]);
    if($e<=16)$encryptedData=substr($encryptedData, 0,strlen($encryptedData)-$e);
    return $encryptedData;
}


$result = aes_encrypt("1234567812345678",'Test String');
$decryptString = aes_decrypt("1234567812345678",$result);

echo $result;
echo $decryptString;

***/


php.print =
function( msg ) {
    console.log(
"echo:", msg)
}
  
php.exec( php.code );
console.pause();

170

主题

2184

回帖

1万

积分

管理员

积分
13236
 楼主| 发表于 2017-11-15 23:07:29 | 显示全部楼层
因为PHP7.1废弃了mcrypt,所以写法不一样,
要保持加解密结果与上面的aardio代码一致,需要这样写:
  1. <?php

  2. //AES加密
  3. function aes_encrypt($key,$str)
  4. {  
  5.     return base64_encode( openssl_encrypt($str, 'AES-128-CBC',$key,OPENSSL_RAW_DATA,$key) );;
  6. }

  7. //AES解密
  8. function aes_decrypt($key,$str)
  9. {
  10.     return openssl_decrypt(base64_decode($str), 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $key);
  11. }

  12. $result = aes_encrypt("1234567812345678",'Test String');
  13. $str = aes_decrypt("1234567812345678",$result);

  14. echo $result."<br>";
  15. echo $str;
  16. ?>
复制代码

170

主题

2184

回帖

1万

积分

管理员

积分
13236
 楼主| 发表于 2017-11-16 00:19:27 | 显示全部楼层
要保持加解密结果与上面的aardio代码一致,Java 需要这样写:
  1. import javax.crypto.spec.IvParameterSpec;
  2. import javax.crypto.Cipher;  
  3. import javax.crypto.KeyGenerator;  
  4. import javax.crypto.SecretKey;  
  5. import javax.crypto.spec.SecretKeySpec;  
  6. import sun.misc.BASE64Decoder;  
  7. import sun.misc.BASE64Encoder;
  8.   
  9. public class AESCrypt {   

  10.     public static String encrypt(String source, String key) throws Exception {
  11.          
  12.         byte[] sourceBytes = source.getBytes("UTF-8");  
  13.         byte[] keyBytes = key.getBytes("UTF-8");
  14.         
  15.         Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");   
  16.         IvParameterSpec ivParameterSpec = new IvParameterSpec(keyBytes);
  17.         cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(keyBytes, "AES"),ivParameterSpec);   
  18.          
  19.         byte[] decrypted = cipher.doFinal(sourceBytes);  
  20.         return new sun.misc.BASE64Encoder().encode(decrypted);  
  21.     }  
  22.         
  23.     public static String decrypt(String encryptStr, String key) throws Exception {  
  24.         byte[] sourceBytes = new sun.misc.BASE64Decoder().decodeBuffer(encryptStr);  
  25.         byte[] keyBytes = key.getBytes("UTF-8");
  26.         
  27.         Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");   
  28.         IvParameterSpec ivParameterSpec = new IvParameterSpec(keyBytes);
  29.         cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(keyBytes, "AES"),ivParameterSpec);
  30.            
  31.         byte[] decoded = cipher.doFinal(sourceBytes);   
  32.         return new String(decoded, "UTF-8");  
  33.     }  
  34.       
  35. }  
复制代码

0

主题

2

回帖

15

积分

新手入门

积分
15
发表于 2017-12-27 15:33:06 | 显示全部楼层
请问下这个aes cbc可不可以把初始向量单独成为一个参数

0

主题

2

回帖

15

积分

新手入门

积分
15
发表于 2017-12-27 15:39:30 | 显示全部楼层
Akkuman 发表于 2017-12-27 15:33
请问下这个aes cbc可不可以把初始向量单独成为一个参数

谢谢了,我刚才仔细看了看实现,知道在哪可以设置初始向量了
您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

手机版|未经许可严禁引用或转载本站文章|aardio.com|aardio 官方社区 ( 皖ICP备09012014号 )

GMT+8, 2024-4-15 05:18 , Processed in 0.055982 second(s), 22 queries .

Powered by Discuz! X3.5

Copyright © 2001-2023 Tencent Cloud.

快速回复 返回顶部 返回列表