`

(转)关于AES256算法java端加密,ios端解密出现无法解密问题的解决方案

阅读更多

我想关于AES算法大家应该都已经了解了,我就不多介绍了。这是本人第一次写技术博文,如果有不对之处欢迎大家指正,共同讨论,一起学习!

      之前在项目上用到AES256加密解密算法,刚开始在java端加密解密都没有问题,在iOS端加密解密也没有问题。但是奇怪的是在java端加密后的文件在iOS端无法正确解密打开,然后简单测试了一下,发现在java端和iOS端采用相同明文,相同密钥加密后的密文不一样!上网查了资料后发现iOS中AES加密算法采用的填充是PKCS7Padding,而java不支持PKCS7Padding,只支持PKCS5Padding。我们知道加密算法由算法+模式+填充组成,所以这两者不同的填充算法导致相同明文相同密钥加密后出现密文不一致的情况。那么我们需要在java中用PKCS7Padding来填充,这样就可以和iOS端填充算法一致了。

      要实现在java端用PKCS7Padding填充,需要用到bouncycastle组件来实现,下面我会提供该包的下载。啰嗦了一大堆,下面是一个简单的测试,上代码!

001 package com.encrypt.file;
002  
003  
004 import java.io.UnsupportedEncodingException;
005 import java.security.Key; 
006 import java.security.Security;
007  
008 import javax.crypto.Cipher; 
009 import javax.crypto.SecretKey; 
010 import javax.crypto.spec.SecretKeySpec; 
011  
012 public class AES256Encryption{ 
013      
014          /**
015          * 密钥算法
016          * java6支持56位密钥,bouncycastle支持64位
017          * */ 
018         public static final String KEY_ALGORITHM="AES"
019            
020         /**
021          * 加密/解密算法/工作模式/填充方式
022          
023          * JAVA6 支持PKCS5PADDING填充方式
024          * Bouncy castle支持PKCS7Padding填充方式
025          * */ 
026         public static final String CIPHER_ALGORITHM="AES/ECB/PKCS7Padding"
027            
028         /**
029          
030          * 生成密钥,java6只支持56位密钥,bouncycastle支持64位密钥
031          * @return byte[] 二进制密钥
032          * */ 
033         public static byte[] initkey() throws Exception{ 
034                
035 //          //实例化密钥生成器 
036 //          Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
037 //          KeyGenerator kg=KeyGenerator.getInstance(KEY_ALGORITHM, "BC"); 
038 //          //初始化密钥生成器,AES要求密钥长度为128位、192位、256位 
039 ////            kg.init(256); 
040 //          kg.init(128);
041 //          //生成密钥 
042 //          SecretKey secretKey=kg.generateKey(); 
043 //          //获取二进制密钥编码形式 
044 //          return secretKey.getEncoded(); 
045             //为了便于测试,这里我把key写死了,如果大家需要自动生成,可用上面注释掉的代码
046             return new byte[] { 0x080x080x040x0b0x020x0f0x0b0x0c,
047                     0x010x030x090x070x0c0x030x070x0a0x040x0f,
048                     0x060x0f0x0e0x090x050x010x0a0x0a0x010x09,
049                     0x060x070x090x0d };
050         }
051  
052         /**
053          * 转换密钥
054          * @param key 二进制密钥
055          * @return Key 密钥
056          * */ 
057         public static Key toKey(byte[] key) throws Exception{ 
058             //实例化DES密钥 
059             //生成密钥 
060             SecretKey secretKey=new SecretKeySpec(key,KEY_ALGORITHM); 
061             return secretKey; 
062         
063            
064         /**
065          * 加密数据
066          * @param data 待加密数据
067          * @param key 密钥
068          * @return byte[] 加密后的数据
069          * */ 
070         public static byte[] encrypt(byte[] data,byte[] key) throws Exception{ 
071             //还原密钥 
072             Key k=toKey(key); 
073             /**
074              * 实例化
075              * 使用 PKCS7PADDING 填充方式,按如下方式实现,就是调用bouncycastle组件实现
076              * Cipher.getInstance(CIPHER_ALGORITHM,"BC")
077              */ 
078             Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
079             Cipher cipher=Cipher.getInstance(CIPHER_ALGORITHM, "BC"); 
080             //初始化,设置为加密模式 
081             cipher.init(Cipher.ENCRYPT_MODE, k); 
082             //执行操作 
083             return cipher.doFinal(data); 
084         
085         /**
086          * 解密数据
087          * @param data 待解密数据
088          * @param key 密钥
089          * @return byte[] 解密后的数据
090          * */ 
091         public static byte[] decrypt(byte[] data,byte[] key) throws Exception{ 
092             //欢迎密钥 
093             Key k =toKey(key); 
094             /**
095              * 实例化
096              * 使用 PKCS7PADDING 填充方式,按如下方式实现,就是调用bouncycastle组件实现
097              * Cipher.getInstance(CIPHER_ALGORITHM,"BC")
098              */ 
099             Cipher cipher=Cipher.getInstance(CIPHER_ALGORITHM); 
100             //初始化,设置为解密模式
101             cipher.init(Cipher.DECRYPT_MODE, k); 
102             //执行操作 
103             return cipher.doFinal(data); 
104         
105         /**
106          * @param args
107          * @throws UnsupportedEncodingException
108          * @throws Exception 
109          */ 
110         public static void main(String[] args) throws UnsupportedEncodingException{ 
111              
112             String str="AES"
113             System.out.println("原文:"+str); 
114  
115             //初始化密钥 
116             byte[] key;
117             try {
118                 key = AES256Encryption.initkey();
119                 System.out.print("密钥:"); 
120                 for(int i = 0;i<key.length;i++){
121                     System.out.printf("%x", key[i]);
122                 }
123                 System.out.print("\n");
124                 //加密数据 
125                 byte[] data=AES256Encryption.encrypt(str.getBytes(), key); 
126                 System.out.print("加密后:");
127                 for(int i = 0;i<data.length;i++){
128                     System.out.printf("%x", data[i]);
129                 }
130                 System.out.print("\n");
131                  
132                 //解密数据 
133                 data=AES256Encryption.decrypt(data, key); 
134                 System.out.println("解密后:"+new String(data));
135             catch (Exception e) {
136                 // TODO Auto-generated catch block
137                 e.printStackTrace();
138             
139               
140         
141     }

      运行程序后的结果截图:

      

      上图可以看到密钥和密文,好了,我们来看看iOS端实现AES256加密解密的方法,有点复杂,大家耐心点看就好。

EncryptAndDecrypt.h文件

01 //
02 //  EncryptAndDecrypt.h
03 //  AES256EncryptionDemo
04 //
05 //  Created by rich sun on 12-12-13.
06 //  Copyright (c) 2012年 rich sun. All rights reserved.
07 //
08  
09 #import <Foundation/Foundation.h>
10  
11 @class NSString;
12  
13 @interface NSData (Encryption)
14  
15 - (NSData *)AES256EncryptWithKey:(NSData *)key;   //加密
16 - (NSData *)AES256DecryptWithKey:(NSData *)key;   //解密
17 - (NSString *)newStringInBase64FromData;            //追加64编码
18 + (NSString*)base64encode:(NSString*)str;           //同上64编码
19  
20 @end

EncryptAndDecrypt.m文件

 

001 //
002 //  EncryptAndDecrypt.m
003 //  AES256EncryptionDemo
004 //
005 //  Created by rich sun on 12-12-13.
006 //  Copyright (c) 2012年 rich sun. All rights reserved.
007 //
008  
009 #import "EncryptAndDecrypt.h"
010 #import <CommonCrypto/CommonCrypto.h>
011 static char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
012  
013 @implementation NSData (Encryption)
014  
015 - (NSData *)AES256EncryptWithKey:(NSData *)key   //加密
016 {
017  
018     //AES256加密,密钥应该是32位的
019     const void * keyPtr2 = [key bytes];
020     char (*keyPtr)[32] = keyPtr2;
021  
022     //对于块加密算法,输出大小总是等于或小于输入大小加上一个块的大小
023     //所以在下边需要再加上一个块的大小
024     NSUInteger dataLength = [self length];
025     size_t bufferSize = dataLength + kCCBlockSizeAES128;
026     void *buffer = malloc(bufferSize);
027  
028     size_t numBytesEncrypted = 0;
029     CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128,
030                                           kCCOptionPKCS7Padding/*这里就是刚才说到的PKCS7Padding填充了*/ | kCCOptionECBMode,
031                                           [key bytes], kCCKeySizeAES256,
032                                           NULL,/* 初始化向量(可选) */
033                                           [self bytes], dataLength,/*输入*/
034                                           buffer, bufferSize,/* 输出 */
035                                           &numBytesEncrypted);
036  
037     if (cryptStatus == kCCSuccess) {
038         return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
039     }
040     free(buffer);//释放buffer
041     return nil;
042 }
043  
044  
045 - (NSData *)AES256DecryptWithKey:(NSData *)key   //解密
046 {
047  
048     //同理,解密中,密钥也是32位的
049     const void * keyPtr2 = [key bytes];
050     char (*keyPtr)[32] = keyPtr2;
051  
052     //对于块加密算法,输出大小总是等于或小于输入大小加上一个块的大小
053     //所以在下边需要再加上一个块的大小
054     NSUInteger dataLength = [self length];
055     size_t bufferSize = dataLength + kCCBlockSizeAES128;
056     void *buffer = malloc(bufferSize);
057  
058     size_t numBytesDecrypted = 0;
059     CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128,
060                                           kCCOptionPKCS7Padding/*这里就是刚才说到的PKCS7Padding填充了*/ | kCCOptionECBMode,
061                                           keyPtr, kCCKeySizeAES256,
062                                           NULL,/* 初始化向量(可选) */
063                                           [self bytes], dataLength,/* 输入 */
064                                           buffer, bufferSize,/* 输出 */
065                                           &numBytesDecrypted);
066     if (cryptStatus == kCCSuccess) {
067         return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
068     }
069     free(buffer);
070     return nil;
071 }
072  
073  
074 - (NSString *)newStringInBase64FromData            //追加64编码
075 {
076     NSMutableString *dest = [[NSMutableString alloc] initWithString:@""];
077     unsigned char * working = (unsigned char *)[self bytes];
078     int srcLen = [self length];
079     for (int i=0; i<srcLen; i += 3) {
080         for (int nib=0; nib<4; nib++) {
081             int byt = (nib == 0)?0:nib-1;
082             int ix = (nib+1)*2;
083             if (i+byt >= srcLen) break;
084             unsigned char curr = ((working[i+byt] << (8-ix)) & 0x3F);
085             if (i+nib < srcLen) curr |= ((working[i+nib] >> ix) & 0x3F);
086             [dest appendFormat:@"%c", base64[curr]];
087         }
088     }
089     return dest;
090 }
091  
092 + (NSString*)base64encode:(NSString*)str
093 {
094     if ([str length] == 0)
095         return @"";
096     const char *source = [str UTF8String];
097     int strlength  = strlen(source);
098     char *characters = malloc(((strlength + 2) / 3) * 4);
099     if (characters == NULL)
100         return nil;
101     NSUInteger length = 0;
102     NSUInteger i = 0;
103     while (i < strlength) {
104         char buffer[3] = {0,0,0};
105         short bufferLength = 0;
106         while (bufferLength < 3 && i < strlength)
107             buffer[bufferLength++] = source[i++];
108         characters[length++] = base64[(buffer[0] & 0xFC) >> 2];
109         characters[length++] = base64[((buffer[0] & 0x03) << 4) | ((buffer[1] & 0xF0) >> 4)];
110         if (bufferLength > 1)
111             characters[length++] = base64[((buffer[1] & 0x0F) << 2) | ((buffer[2] & 0xC0) >> 6)];
112         else characters[length++] = '=';
113         if (bufferLength > 2)
114             characters[length++] = base64[buffer[2] & 0x3F];
115         else characters[length++] = '=';
116     }
117     NSString *g = [[NSString alloc] initWithBytesNoCopy:characters length:length encoding:NSASCIIStringEncoding freeWhenDone:YES];
118     return g;
119 }
120  
121 @end

      ViewController.m文件

 

01 //
02 //  ViewController.m
03 //  AES256EncryptionDemo
04 //
05 //  Created by 孙 裔 on 12-12-13.
06 //  Copyright (c) 2012年 rich sun. All rights reserved.
07 //
08  
09 #import "ViewController.h"
10 #import "EncryptAndDecrypt.h"
11  
12 @interface ViewController ()
13  
14 @end
15  
16 @implementation ViewController
17 @synthesize plainTextField;
18 - (void)viewDidLoad
19 {
20     [super viewDidLoad];
21     // Do any additional setup after loading the view, typically from a nib.
22 }
23  
24 - (void)didReceiveMemoryWarning
25 {
26     [super didReceiveMemoryWarning];
27     // Dispose of any resources that can be recreated.
28 }
29 //这个函数实现了用户输入完后点击视图背景,关闭键盘
30 - (IBAction)backgroundTap:(id)sender{
31     [plainTextField resignFirstResponder];
32 }
33  
34 - (IBAction)encrypt:(id)sender {
35      
36     NSString *plainText = plainTextField.text;//明文
37     NSData *plainTextData = [plainText dataUsingEncoding:NSUTF8StringEncoding];
38      
39     //为了测试,这里先把密钥写死
40     Byte keyByte[] = {0x08,0x08,0x04,0x0b,0x02,0x0f,0x0b,0x0c,0x01,0x03,0x09,0x07,0x0c,0x03,
41         0x07,0x0a,0x04,0x0f,0x06,0x0f,0x0e,0x09,0x05,0x01,0x0a,0x0a,0x01,0x09,
42         0x06,0x07,0x09,0x0d};
43     //byte转换为NSData类型,以便下边加密方法的调用
44     NSData *keyData = [[NSData alloc] initWithBytes:keyByte length:32];
45     //
46     NSData *cipherTextData = [plainTextData AES256EncryptWithKey:keyData];
47     Byte *plainTextByte = (Byte *)[cipherTextData bytes];
48     for(int i=0;i<[cipherTextData length];i++){
49         printf("%x",plainTextByte[i]);
50     }
51  
52 }
53 @end

 

运行程序,这里需要自己创建一个简单的应用程序,简单的布局:


加密后的密文:


      大家可以看到这里的密文和java端的密文是一致的,这样我们就成功完成了。只要密文和密钥是一致的,那么解密应该就不会有什么问题了后面如果有需要解密的可以自己调用解密的那个方法就可以了。

      如有什么不明之处欢迎大家留言,互相学习!很遗憾这里无法上传附件,代码中需要的包只能以链接的方式让各位去下了:

jce_policy-6.zip 下载链接:http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html

下载解压后将里边的两个jar包(local_policy.jar,US_export_policy.jar)替换掉jdk安装路径下security文件夹中的两个包。

bcprov-jdk16-139.jar 下载链接:http://www.bouncycastle.org

      终于写完了。。。第一次写博文,虽然有点费时,但感觉很好!如有转载,请注明出处,谢谢大家!

 

NSString *str = @"AA21f0c1762a3abc299c013abe7dbcc50001DD"
怎么将里面的字符转换到Byte数组中,如下
Byte buffer[] = { 0xAA, 0x21, 0xf0, 0xc1, 0x76, 0x2a, 0x3a, ... , 0x01, 0xDD }
各位大侠恳请帮帮忙,先谢谢啦
找到答案了,
@interface NSString (NSStringHexToBytes)
-(NSData*) hexToBytes ;
@end
@implementation NSString (NSStringHexToBytes)
-(NSData*) hexToBytes {
    NSMutableData* data = [NSMutableDatadata];
    int idx;
    for (idx = 0; idx+2 <= self.length; idx+=2) {
        NSRange range = NSMakeRange(idx, 2);
        NSString* hexStr = [selfsubstringWithRange:range];
        NSScanner* scanner = [NSScannerscannerWithString:hexStr];
        unsignedint intValue;
        [scanner scanHexInt:&intValue];
        [data appendBytes:&intValue length:1];
    }
    return data;
}
@end

应用:
NSData *data = [str hexToBytes];
 
 
2012-11-06 18:49提问者采纳
 
NSString *str = @"AA21f0c1762a3abc299c013abe7dbcc50001DD";

NSData* bytes = [str dataUsingEncoding:NSUTF8StringEncoding];
Byte * myByte = (Byte *)[bytes bytes];
NSLog(@"myByte = %s",myByte);
分享到:
评论

相关推荐

    AES加密解密算法 iOS和Android完美实现

    在iOS和Android平台上实现AES加密解密是开发者经常遇到的任务,尤其对于需要跨平台传输和存储敏感信息的场景。本篇文章将详细探讨AES加密解密算法在iOS和Android平台上的实现原理以及具体步骤。 首先,AES算法基于...

    AES加密解密,iOS,Android,Java,.Net通用

    AES加密有多种算法模式,下面提供两套模式的可用源码: 一、CBC(Cipher Block Chaining,加密块链)模式 二、ECB(Electronic Code Book,电子密码本)模式 其中CBC模式下,有.NET的源码。而ECB模式的,大家在网上找...

    uniapp 前后端AES加密解密.rar

    本压缩包"uniapp 前后端AES加密解密.rar"正是为了解决这一问题,它包含了在uniapp环境下实现前后端AES加密解密的方法。AES(Advanced Encryption Standard),即高级加密标准,是一种广泛使用的对称加密算法,具有...

    iOS AES加密解密

    在iOS开发中,AES(Advanced Encryption Standard)是一种广泛使用的对称加密算法,用于保护数据的安全性。AES128指的是使用128位的密钥进行加密,这提供了极高的安全级别,使得破解变得极其困难。本文将深入探讨iOS...

    高性能AES256对称加解密,兼容Java、IOS、Android,带注释和使用方法

    AES256是一种广泛使用的对称加密算法,全称为Advanced Encryption Standard with a 256-bit key size。这种加密标准在信息安全领域具有很高的安全性,被用于保护敏感数据,如密码、个人信息以及商业机密等。它基于块...

    ios AES加密解密

    AES是一种对称加密算法,它使用相同的密钥进行加密和解密,具有速度快、安全性高的特点。本篇将详细介绍如何在iOS应用中实现AES加密解密。 一、AES加密原理 AES加密基于替换和置换操作,通过128位的块进行加密,...

    iOS AES128加密解密

    **iOS中的AES128加密解密** AES(Advanced Encryption Standard),即高级加密标准,是目前广泛用于数据安全保护的一种对称加密算法。在iOS开发中,AES128是常见的加密方式,常用于保护敏感数据,如用户密码、隐私...

    ios NSData NSString AES加密解密算法源码

    理解并掌握这种AES加密解密方法对于iOS开发者来说非常关键,可以有效地保护应用程序的数据安全,防止未授权访问。同时,了解如何在Objective-C中使用CommonCrypto库也可以扩展到其他加密算法的实现,如RSA或DES。在...

    iOS AES加密 PHP解密

    AES(Advanced Encryption Standard)是一种广泛应用的对称加密算法,它提供了高效且安全的数据加密。本话题将围绕“iOS AES加密 PHP解密”这一主题展开,讲解如何在iOS应用中使用AES加密数据,并在后端PHP环境中...

    DES加密解密一套JAVA&IOS

    本资源"DES加密解密一套JAVA&IOS"提供了一套跨平台的解决方案,允许JAVA和iOS应用之间进行互操作性的加密和解密操作。 在JAVA平台上,DES加密和解密通常通过Java的`javax.crypto`包来实现。这个包提供了`Cipher`类...

    IOS JAVA AES128加密解密

    AES(Advanced Encryption Standard)128位加密是一种广泛应用的对称加密算法,它为iOS、Android、Java等平台提供了强大的安全保障。本篇文章将深入探讨AES128加密解密的原理、实现方式以及在不同平台上的应用。 ...

    java/javascript/iOS的AES加解密(AES/CBC/PKCS5Padding)

    本文将深入探讨AES加密,特别是使用CBC(Cipher Block Chaining,密码块链接)模式和PKCS5Padding填充方式,并在JavaScript、Java和iOS平台上实现这一加密过程。 **一、AES加密简介** AES是一种对称加密算法,由...

    AES加密 – Java与android、iOS、js的同步实现

    文件"js aes.txt"可能是JavaScript实现AES加密的示例代码,而"AES加密 – iOS与Java的同步实现"可能是介绍如何在iOS和Java之间实现同步加密的教程或代码示例。通过学习这些内容,开发者可以掌握如何在不同平台上实现...

    AES加密解密,iOS,Android,Java通用

    本工程可以直接使用,而且与IOS,Android,JAVA 已调通。...AES加密有多种算法模式,下面提供两套模式的可用源码: 一、CBC(Cipher Block Chaining,加密块链)模式 二、ECB(Electronic Code Book,电子密码本)模式

    IOS RSA加密 分段解密

    在iOS开发中,RSA是一种广泛使用的非对称加密算法,主要应用于数据的加密和数字签名。RSA的安全性基于大整数因子分解的困难性,它包括一对密钥:公钥和私钥。公钥用于加密,私钥用于解密。在处理大量数据时,由于RSA...

    Object-C-在iOS上使用Object-C进行RSA算法的加密+解密实现.zip

    总之,使用Object-C在iOS上实现RSA加密解密涉及理解算法原理、导入导出密钥、调用Security框架的API以及处理可能出现的问题。通过掌握这些知识,开发者可以创建安全的应用程序,保护用户数据的安全。

Global site tag (gtag.js) - Google Analytics