zoukankan      html  css  js  c++  java
  • C#, Java, PHP, Python和Javascript几种语言的AES加密解密实现

    特别提示:本人博客部分有参考网络其他博客,但均是本人亲手编写过并验证通过。如发现博客有错误,请及时提出以免误导其他人,谢谢!欢迎转载,但记得标明文章出处:http://www.cnblogs.com/mao2080/

    1、问题描述

      在与C同事调试的时候发现,Java加密的文件,C语言解析不了,后面找了很多才找到解决方案。

    2、操作方法

      1、Java加密解密

    import javax.crypto.Cipher;
    import javax.crypto.spec.IvParameterSpec;
    import javax.crypto.spec.SecretKeySpec;
    import org.junit.Test;
    ...
      @Test
      public void testCrossLanguageEncrypt() throws Exception{
        System.out.println(encrypt());
        System.out.println(desEncrypt());
      }
      public static String encrypt() throws Exception {
        try {
          String data = "Test String";
          String key = "1234567812345678";
          String iv = "1234567812345678";
          Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
          int blockSize = cipher.getBlockSize();
          byte[] dataBytes = data.getBytes();
          int plaintextLength = dataBytes.length;
          if (plaintextLength % blockSize != 0) {
            plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
          }
          byte[] plaintext = new byte[plaintextLength];
          System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);
          SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
          IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
          cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
          byte[] encrypted = cipher.doFinal(plaintext);
          return new sun.misc.BASE64Encoder().encode(encrypted);
        } catch (Exception e) {
          e.printStackTrace();
          return null;
        }
      }
      public static String desEncrypt() throws Exception {
        try
        {
          String data = "2fbwW9+8vPId2/foafZq6Q==";
          String key = "1234567812345678";
          String iv = "1234567812345678";
          byte[] encrypted1 = new sun.misc.BASE64Decoder().decodeBuffer(data);
          Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
          SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
          IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
          cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
          byte[] original = cipher.doFinal(encrypted1);
          String originalString = new String(original);
          return originalString;
        }
        catch (Exception e) {
          e.printStackTrace();
          return null;
        }
      }
    

      2、C加密解密

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Security.Cryptography;
    namespace test
    {
      class Class1
      {
        static void Main(string[] args)
        {
          Console.WriteLine("I am comming");
          String source = "Test String";
          String encryptData = Class1.Encrypt(source, "1234567812345678", "1234567812345678");
          Console.WriteLine("=1==");
          Console.WriteLine(encryptData);
          Console.WriteLine("=2==");
          String decryptData = Class1.Decrypt("2fbwW9+8vPId2/foafZq6Q==", "1234567812345678", "1234567812345678");
          Console.WriteLine(decryptData);
          Console.WriteLine("=3==");
          Console.WriteLine("I will go out");
        }
        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 rDel = new RijndaelManaged();
          rDel.Key = keyArray;
          rDel.IV = ivArray;
          rDel.Mode = CipherMode.CBC;
          rDel.Padding = PaddingMode.Zeros;
          ICryptoTransform cTransform = rDel.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 rDel = new RijndaelManaged();
          rDel.Key = keyArray;
          rDel.IV = ivArray;
          rDel.Mode = CipherMode.CBC;
          rDel.Padding = PaddingMode.Zeros;
          ICryptoTransform cTransform = rDel.CreateDecryptor();
          byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
          return UTF8Encoding.UTF8.GetString(resultArray);
        }
      }
    }
    

      3、PHP加密解密

    <?php
    $privateKey = "1234567812345678";
    $iv     = "1234567812345678";
    $data   = "Test String";
     
    //加密
    $encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $privateKey, $data, MCRYPT_MODE_CBC, $iv);
    echo($encrypted);
    echo '<br/>';
    echo(base64_encode($encrypted));
    echo '<br/>';
     
    //解密
    $encryptedData = base64_decode("2fbwW9+8vPId2/foafZq6Q==");
    $decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $privateKey, $encryptedData, MCRYPT_MODE_CBC, $iv);
    echo($decrypted);
    ?>
    

      4、JS加密解密

    <script type="text/javascript" src="aes.js"></script>
        <script type="text/javascript" src="pad-zeropadding.js"></script>
    导入文件,aes.js需要导入crypto-js压缩包中rollups文件夹下的那个aes.js文件,如果引入的是components文件夹下的aes.js是会报错的
    
    <script type="text/javascript">
      var data = "Test String";
      var key  = CryptoJS.enc.Latin1.parse('1234567812345678');
      var iv   = CryptoJS.enc.Latin1.parse('1234567812345678');
      //加密
      var encrypted = CryptoJS.AES.encrypt(data,key,{iv:iv,mode:CryptoJS.mode.CBC,padding:CryptoJS.pad.ZeroPadding});
      document.write(encrypted.ciphertext);
      document.write('<br/>');
      document.write(encrypted.key);
      document.write('<br/>');
      document.write(encrypted.iv);
      document.write('<br/>');
      document.write(encrypted.salt);
      document.write('<br/>');
      document.write(encrypted);
      document.write('<br/>');
      //解密
      var decrypted = CryptoJS.AES.decrypt(encrypted,key,{iv:iv,padding:CryptoJS.pad.ZeroPadding});
      console.log(decrypted.toString(CryptoJS.enc.Utf8));
        </script>
    

      5、python加密解密

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    from Crypto.Cipher import AES
    import base64
    PADDING = ''
    #PADDING = ' '
    pad_it = lambda s: s+(16 - len(s)%16)*PADDING  
    key = '1234567812345678'
    iv = '1234567812345678'
    source = 'Test String'
    generator = AES.new(key, AES.MODE_CBC, iv)
    crypt = generator.encrypt(pad_it(source))   
    cryptedStr = base64.b64encode(crypt)
    print cryptedStr
    generator = AES.new(key, AES.MODE_CBC, iv)
    recovery = generator.decrypt(crypt)
    print recovery.rstrip(PADDING)
    

      注意python下需要用''来填充,如果是空格来填充,python加密得到的字符串会跟其他语言不同。另外注意generator在加密的时候使用过,解密的时候需重新生成再解密,否则解密失败。最后得到的字符串,在python控制台看到尾部是多个NUL这样的东西,要这样recovery.rstrip(PADDING)去除掉才是原始字符串。

    可以看到aes加密的中间结果是byte[]类型,直接new String(byte[])会看不到有意义的中间结果,这里用的是base64,是因为各个语言都有这样的支持。在同个语言内,也有bytesToHexString这样的方式。

    跨语言加解密的要求是:AES/CBC/ZeroPadding 128位模式,key和iv一样,编码统一用utf-8。不支持ZeroPadding的就用NoPadding.

    3、参考网站

      https://blog.csdn.net/buster2014/article/details/50939194

  • 相关阅读:
    LeetCode 453 Minimum Moves to Equal Array Elements
    LeetCode 112 Path Sum
    LeetCode 437 Path Sum III
    LeetCode 263 Ugly Number
    Solutions and Summay for Linked List Naive and Easy Questions
    AWS–Sysops notes
    Linked List
    All About Linked List
    datatable fix error–Invalid JSON response
    [转]反编译c#的相关问题
  • 原文地址:https://www.cnblogs.com/mao2080/p/10500612.html
Copyright © 2011-2022 走看看