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

    原文:http://outofmemory.cn/code-snippet/35524/AES-with-javascript-java-csharp-python-or-php

    c#里面的AES加密解密

    在visual studio中写的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);
            }
        }
    }
     

    其中加密后以及解密后的字符串都能成功打印,但Console.WriteLine("=3==");之后的输出就没有了,最后输出个线程返回值0,然后就没有然后了。c#不懂,就不深究了,就已执行的部分,是符合要求了。

    Java的AES加密解密:

    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;
            }
        }
     

    php的AES加密解密

    php代码,php很多东西都是提供好的,直接用函数,但是php目前所知填充模式只有ZeroPadding,于是其他语言就只能跟着它来了:

    <?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);
    ?>
     

    Javascript下aes加解密,试过也可以,需要在https://code.google.com/p/crypto-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>

    成功加解密,最后解密的字符串串在浏览器的控制台里才能看到。

    python的AES加密解密

    最后加一个python下的aes,需要安装python Crypto:

    #!/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.

  • 相关阅读:
    168. Excel Sheet Column Title
    171. Excel Sheet Column Number
    264. Ugly Number II java solutions
    152. Maximum Product Subarray java solutions
    309. Best Time to Buy and Sell Stock with Cooldown java solutions
    120. Triangle java solutions
    300. Longest Increasing Subsequence java solutions
    63. Unique Paths II java solutions
    221. Maximal Square java solutions
    279. Perfect Squares java solutions
  • 原文地址:https://www.cnblogs.com/dreign/p/4332569.html
Copyright © 2011-2022 走看看