AES 128使用预定义密钥实现

Dav*_*vid 1 encryption android

我正在尝试在Android上实现AES128算法,我已经引用了这个链接用于基本的AES实现(http://java.sun.com/developer/technicalArticles/Security/AES/AES_v1.html).

问题是,对于我的项目,密钥是预定义的,它是36字节,而不是16/24/32字节.所以我总是得到"密钥长度不是128/194/256位"的例外.我尝试了iphone sdk的解决方案(参见此链接:iOS加密框架),即使我传递36字节预定义密钥也能正常工作.由于我找不到Apple发布的BlockCipher.c/CommonCryptor.c的实现细节,任何正文都可以帮我弄清楚他们如何从36个字节中选择16个字节?

谢谢.

-----------------------------------更新9月13日------------ ------------------------为了避免混淆,我提供了一些样本和我的进展.我更改了一些保密的数据,但长度和格式保持不变.为节省时间,我只透露核心功能.没有对代码的评论,因为我认为代码是自我解释的.

iOS示例:

NSString * _key = @"some 36 byte key";
StringEncryption *crypto = [[[StringEncryption alloc] init] autorelease]; 
NSData *_inputData = [inputString dataUsingEncoding:NSUTF8StringEncoding]; 
CCOptions padding = kCCOptionPKCS7Padding;
NSData *encryptedData = [crypto encrypt:_inputData key:[_key dataUsingEncoding:NSUTF8StringEncoding] padding:&padding];
NSString *encryptedString = [encryptedData base64EncodingWithLineLength:0];
return encryptedString;
Run Code Online (Sandbox Code Playgroud)

[crypto encrypt]实现与我上面提到的链接完全相同.它以加密模式调用doCipher.核心功能包括CCCryptorCreate,CCCryptorUpdate和CCCryptorFinal,它们来自.CCCryptorCreate处理密钥长度.它传递原始密钥字节,并传递一个整数16(kCCKeySizeAES128)作为密钥大小并执行操作.调用层次结构类似于CCCryptorCreate/CommonCryptor.c => ccBlockCipherCallouts-> CCBlockCipherInit/BlockCipher.c => ccAlgInfo-> setkey/BlockCipher.c.setkey实际上是指向函数的指针,对于AES,它指向aes_cc_set_key.我找不到aes_cc_set_key的实现,在这里迷路了.

---------------------------------------- 9月13日更新------- ----------------------我在iOS示例代码中更改_key,手动将前16个字节作为新密钥,其他部分保持不变,并且工作中!!!到目前为止,我解决了密钥长度问题.

但是Android版本的输出与iOS版本不同,用于一些长文本,例如30或40字节.我的java实现如下:

String key = "some 16 byte key";
byte[] keyBytes = key.getBytes("UTF-8");
byte[] plainBytes = plainText.getBytes("UTF-8");
SecretKeySpec skeySpec = new SecretKeySpec(keyBytes, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(plainBytes);
String result = Base64.encodeBytes(encrypted);
return result;
Run Code Online (Sandbox Code Playgroud)

Base64来自org.apache.commons.codec.binary.Base64.问题是什么?或者c/c ++库上可以做同样事情的任何提示?我也可以将它导入到android中.

Cod*_*odo 5

剩下的差异(假设您只使用了密钥的前16个字节)是密码流模式.iOS代码使用CBC模式,初始化设置为全零.然而,Android代码使用ECB.

所以正确的Java/Android代码是:

// convert key to bytes
byte[] keyBytes = key.getBytes("UTF-8");
// Use the first 16 bytes (or even less if key is shorter)
byte[] keyBytes16 = new byte[16];
System.arraycopy(keyBytes, 0, keyBytes16, 0, Math.min(keyBytes.length, 16));

// convert plain text to bytes
byte[] plainBytes = plainText.getBytes("UTF-8");

// setup cipher
SecretKeySpec skeySpec = new SecretKeySpec(keyBytes16, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] iv = new byte[16]; // initialization vector with all 0
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(iv));

// encrypt
byte[] encrypted = cipher.doFinal(plainBytes);
Run Code Online (Sandbox Code Playgroud)

我用大约100个字节的数据测试了它,并在iOS和Java上获得了完全相同的结果.