<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    C#對(duì)稱(chēng)加密算法Java實(shí)現(xiàn)

    最近因?yàn)闃I(yè)務(wù)需求,需要把一段C#編寫(xiě)的加密代碼采用Java進(jìn)行實(shí)現(xiàn),在此記下我的實(shí)施過(guò)程和過(guò)程中碰到的一些問(wèn)題以備后用。為了便于觀察,只貼上C#源碼中關(guān)鍵的部分:
     1 ///
     2 ///<summary>
     3 /// 加密方法
     4 /// </summary>
     5 /// <param name=\"Source\">待加密的串</param>
     6 /// <returns>經(jīng)過(guò)加密的串</returns>
     7 public static string Encrypto(string Source)
     8 {
     9     byte[] bytIn = UTF8Encoding.UTF8.GetBytes(Source);
    10     MemoryStream ms = new MemoryStream();
    11     mobjCryptoService.Key = GetLegalKey();
    12     mobjCryptoService.IV = GetLegalIV();
    13     //創(chuàng)建對(duì)稱(chēng)加密器對(duì)象
    14     //下面的控制臺(tái)打印是我自己添加方便觀察的
    15     Console.WriteLine("KeySize:" + mobjCryptoService.KeySize);
    16     Console.WriteLine("LegalKeySizes:" + mobjCryptoService.LegalKeySizes.Length);
    17     Console.WriteLine("Mode:"+ mobjCryptoService.Mode);
    18     Console.WriteLine("Padding:"+mobjCryptoService.Padding);
    19     ICryptoTransform encrypto = mobjCryptoService.CreateEncryptor();
    20     //定義將數(shù)據(jù)流鏈接到加密轉(zhuǎn)換的流
    21     CryptoStream cs = new CryptoStream(ms, encrypto, CryptoStreamMode.Write);
    22     cs.Write(bytIn, 0, bytIn.Length);
    23     cs.FlushFinalBlock();
    24     ms.Close();
    25     byte[] bytOut = ms.ToArray();
    26 
    27     return Convert.ToBase64String(bytOut);
    28 }
    29 
    30 ///
    31 ///<summary>
    32 /// 解密方法
    33 /// </summary>
    34 /// <param name=\"Source\">待解密的串</param>
    35 /// <returns>經(jīng)過(guò)解密的串</returns>
    36 public static string Decrypto(string Source)
    37 {
    38     try
    39     {
    40         byte[] bytIn = Convert.FromBase64String(Source);
    41         MemoryStream ms = new MemoryStream(bytIn, 0, bytIn.Length);
    42         mobjCryptoService.Key = GetLegalKey();
    43         mobjCryptoService.IV = GetLegalIV();
    44         //創(chuàng)建對(duì)稱(chēng)解密器對(duì)象
    45         ICryptoTransform encrypto = mobjCryptoService.CreateDecryptor();
    46         //定義將數(shù)據(jù)流鏈接到加密轉(zhuǎn)換的流
    47         CryptoStream cs = new CryptoStream(ms, encrypto, CryptoStreamMode.Read);
    48         StreamReader sr = new StreamReader(cs);
    49         return sr.ReadToEnd();
    50     }
    51     catch (Exception)
    52     {
    53         return string.Empty;
    54     }
    55 }

    其中有一個(gè)問(wèn)題:
    1 //生成加密器的對(duì)象由RijndaelManaged得來(lái),那么這個(gè)RijndaelManaged對(duì)象是干嘛的?第三方的?原生的?
    2 private static SymmetricAlgorithm mobjCryptoService = new RijndaelManaged();

    調(diào)查之后,好吧,它是一種對(duì)稱(chēng)加密算法(可以理解為在雙方之間可以實(shí)現(xiàn)加解密),以下來(lái)自百科:
    高級(jí)加密標(biāo)準(zhǔn)(英語(yǔ):Advanced Encryption Standard,縮寫(xiě):AES),在密碼學(xué)中又稱(chēng)Rijndael加密法,是美國(guó)聯(lián)邦政府采用的一種區(qū)塊加密標(biāo)準(zhǔn)。這個(gè)標(biāo)準(zhǔn)用來(lái)替代原先的DES,已經(jīng)被多方分析且廣為全世界所使用。經(jīng)過(guò)五年的甄選流程,高級(jí)加密標(biāo)準(zhǔn)由美國(guó)國(guó)家標(biāo)準(zhǔn)與技術(shù)研究院(NIST)于2001年11月26日發(fā)布于FIPS PUB 197,并在2002年5月26日成為有效的標(biāo)準(zhǔn)。2006年,高級(jí)加密標(biāo)準(zhǔn)已然成為對(duì)稱(chēng)密鑰加密中最流行的算法之一。
    之前對(duì)加密標(biāo)準(zhǔn)認(rèn)識(shí)的并不多,但是通過(guò)代碼來(lái)看,似乎實(shí)現(xiàn)對(duì)稱(chēng)加密還需要?jiǎng)e的材料,看到下面這兩個(gè)方法
     1 /// <summary>
     2 /// 獲得密鑰
     3 /// </summary>
     4 /// <returns>密鑰</returns>
     5 private static byte[] GetLegalKey()
     6 {
     7     string _TempKey = Key;//Key已經(jīng)預(yù)先寫(xiě)死在代碼里了
     8     mobjCryptoService.GenerateKey();
     9     byte[] bytTemp = mobjCryptoService.Key;
    10     int KeyLength = bytTemp.Length;
    11     if (_TempKey.Length > KeyLength)
    12         _TempKey = _TempKey.Substring(0, KeyLength);
    13     else if (_TempKey.Length < KeyLength)
    14         _TempKey = _TempKey.PadRight(KeyLength, ' ');
    15       return ASCIIEncoding.ASCII.GetBytes(_TempKey);
    16 }
    17 //GetLegalKey方法每次都會(huì)返回一個(gè)長(zhǎng)度為32的byte數(shù)組
    18 //mobjCryptoService.Key = GetLegalKey();
    19 
    20 /// <summary>
    21 /// 獲得初始向量IV
    22 /// </summary>
    23 /// <returns>初試向量IV</returns>
    24 private static byte[] GetLegalIV()
    25 {
    26     string _TempIV = "$%^&*()_osudghwe7%%2kdijskldglk2397^&*wigwuqwelkn";//這是虛構(gòu)的
    27     mobjCryptoService.GenerateIV();
    28     byte[] bytTemp = mobjCryptoService.IV;
    29     int IVLength = bytTemp.Length;
    30     if (_TempIV.Length > IVLength)
    31         _TempIV = _TempIV.Substring(0, IVLength);
    32     else if (_TempIV.Length < IVLength)
    33         _TempIV = _TempIV.PadRight(IVLength, ' ');
    34     return ASCIIEncoding.ASCII.GetBytes(_TempIV);
    35 }
    36 //GetLegalIV方法每次都會(huì)返回一個(gè)長(zhǎng)度為16的byte數(shù)組
    37 //mobjCryptoService.IV = GetLegalIV();

    雖然是通過(guò)兩個(gè)方法來(lái)取得的KEY和IV(二者都是byte數(shù)組),但是KEY和IV都是預(yù)先寫(xiě)死在代碼里的,只不過(guò)是返回了特定長(zhǎng)度的byte數(shù)組。
    1 //RijndaelManaged,這是對(duì)稱(chēng)算法合法的key和IV的長(zhǎng)度(分別以位來(lái)計(jì)算)
    2 //        Legal min key size = 128
    3 //        Legal max key size = 256
    4 //        Legal min block size = 128
    5 //        Legal max block size = 256

    經(jīng)過(guò)調(diào)查,還需要配置算法的mode和padding,此處并沒(méi)有進(jìn)行設(shè)置,所以默認(rèn)分別為CipherMode.CBC和PaddingMode.PKCS7。詳見(jiàn)modepadding

    目前來(lái)看,需要調(diào)查的可以告一段落了,那么接下來(lái),就需要調(diào)查如何Java實(shí)現(xiàn)了。在Java中,實(shí)現(xiàn)加密需要用到JCE提供的Cipher對(duì)象,類(lèi)比C#的實(shí)現(xiàn),借鑒廣大程序員的智慧,我首先嘗試寫(xiě)了一下(只貼出關(guān)鍵部分)
     1 public void init(byte[] keyBytes) {
     2 
     3     // 如果密鑰不足16位,那么就補(bǔ)足. 這個(gè)if 中的內(nèi)容很重要
     4     int base = 16;
     5     if (keyBytes.length % base != 0) {
     6         int groups = keyBytes.length / base
     7                 + (keyBytes.length % base != 0 ? 1 : 0);
     8         byte[] temp = new byte[groups * base];
     9         Arrays.fill(temp, (byte) 0);
    10         System.arraycopy(keyBytes, 0, temp, 0, keyBytes.length);
    11         keyBytes = temp;
    12     }
    13     // 轉(zhuǎn)化成JAVA的密鑰格式
    14     key = new SecretKeySpec(keyBytes, "AES");
    15     try {
    16         // 初始化cipher
    17         cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    18     } catch (NoSuchAlgorithmException e) {
    19         e.printStackTrace();
    20     } catch (NoSuchPaddingException e) {
    21         e.printStackTrace();
    22     } 
    23 }
    24 
    25 /**
    26  * 加密方法
    27  * @param content 待加密內(nèi)容字符串
    28  * @param keySrc 加解密密秘鑰字符串
    29  * @param iv 算法所需向量
    30  * @return
    31  * @throws UnsupportedEncodingException
    32  */
    33 public String encrypt(String content, String keySrc,String iv) throws UnsupportedEncodingException {
    34     byte[] encryptedText = null;
    35     init(keySrc.getBytes("utf-8"));
    36     try {
    37         cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv.getBytes()));
    38         encryptedText = cipher.doFinal(content.getBytes("utf-8"));
    39     } catch (Exception e) {
    40         e.printStackTrace();
    41     }
    42     return Base64.encodeBase64String(encryptedText);
    43 }
    44 
    45 /**
    46  * 解密方法
    47  * @param encryptedData 待解密數(shù)據(jù)
    48  * @param keySrc 加解密密秘鑰字符串
    49  * @param iv 算法所需向量
    50  * @return
    51  * @throws UnsupportedEncodingException 
    52  */
    53 public String decrypt(String encryptedData, String keySrc,String iv) throws UnsupportedEncodingException {
    54     byte[] decryptedText = null;
    55     init(keySrc.getBytes("utf-8"));
    56     try {
    57         cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv.getBytes()));
    58         decryptedText = cipher.doFinal(Base64.decodeBase64(encryptedData));
    59     } catch (Exception e) {
    60         e.printStackTrace();
    61     }
    62     return new String(decryptedText);
    63 }
    64 
    65 public static void main(String[] args) throws UnsupportedEncodingException {
    66     EncryptingUtil eu = new EncryptingUtil();
    67     
    68     String content = "abc";
    69     // 加密字符串
    70     System.out.println("加密前的:" + content);
    71     // 加密方法
    72     String enc = eu.encrypt(content,"秘鑰值","向量值");
    73     System.out.println(enc);
    74     // 解密方法
    75     String dec = eu.decrypt(enc,"秘鑰值", "向量值");
    76     System.out.println("解密后的內(nèi)容:" + dec);
    77 }

    Java版本的實(shí)現(xiàn),目前有幾個(gè)問(wèn)題,一個(gè)就是補(bǔ)齊方式的問(wèn)題,在C#中默認(rèn)的補(bǔ)齊方式PKCS7,但是Java默認(rèn)并不支持該補(bǔ)齊方式,只有PKCS5;其次就是秘鑰的長(zhǎng)度問(wèn)題,C#代碼中的秘鑰長(zhǎng)度是256位的,但是Java默認(rèn)最大支持128位的,執(zhí)行時(shí)會(huì)報(bào)出”Illegal key size”的問(wèn)題。這位大牛的東東幫到我了,感謝。查看

    當(dāng)需要使用256位長(zhǎng)度的秘鑰時(shí),需要下載對(duì)應(yīng)Java版本的JCE拓展包,圖中的問(wèn)題就是因?yàn)镴CE拓展包和Java版本不匹配引起的

    posted on 2016-03-28 22:12 都較瘦 閱讀(204) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): 工具案例積累Java相關(guān)案例積累


    只有注冊(cè)用戶(hù)登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    <2016年3月>
    282912345
    6789101112
    13141516171819
    20212223242526
    272829303112
    3456789

    導(dǎo)航

    統(tǒng)計(jì)

    公告

    博客定位:囿于目前的水平,博客定位在記錄自己的學(xué)習(xí)心得和隨手的練習(xí)

    常用鏈接

    留言簿

    隨筆分類(lèi)

    隨筆檔案

    文章分類(lèi)

    文章檔案

    搜索

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    主站蜘蛛池模板: 一级毛片在线播放免费| 亚洲愉拍一区二区三区| 又黄又爽一线毛片免费观看| 69视频在线是免费观看| 国产99精品一区二区三区免费| 亚洲五月综合缴情婷婷| 亚洲av日韩av无码| 亚洲综合在线另类色区奇米| 青柠影视在线观看免费高清 | 国产成人无码综合亚洲日韩| 国产精品成人免费综合| 国产日韩久久免费影院| 久久综合亚洲鲁鲁五月天| AV免费网址在线观看| 91精品国产免费| 大地资源中文在线观看免费版| 七次郎成人免费线路视频 | 日本免费的一级v一片| 国产国产人免费视频成69堂| 亚洲国产精品自在自线观看| 亚洲色偷拍另类无码专区| 日日麻批免费40分钟日本的| 久久免费国产视频| 久久国产免费一区二区三区| 三上悠亚在线观看免费| 久久久久久av无码免费看大片| 黄视频在线观看免费| 粉色视频成年免费人15次| 久久99亚洲网美利坚合众国| 国产区卡一卡二卡三乱码免费 | 日韩亚洲欧洲在线com91tv| 久久亚洲色一区二区三区| 亚洲最大av无码网址| 亚洲无码高清在线观看| 亚洲一级黄色视频| 国外亚洲成AV人片在线观看| 久久亚洲高清综合| 久久亚洲AV午夜福利精品一区| 亚洲人成依人成综合网| 亚洲国产精品日韩| 亚洲精品无码午夜福利中文字幕|