这几天再做一个项目,服务器和移动端要进行数据传输,但有选择了DES加解密;可是起初一直不能很好的互相加解。
下面上代码,说几个需要注意保持一致的地方。
需要注意的几个参数,首先key要各个端保持一致;
然后iv也要保持一致,不然加密解密会不一样。
其中java会遇到一个报错 Wrong IV length: must be 8 bytes long:这个是key的长度造成的,但官方说密钥是56位长度,这个有点不太明白,但你只要记住key的长度必须是8位。
IV向量:主要作用就是防止篡改的,这个地方如果不一致会导致数据的头部解出来是乱码,而后面正常。(所以有时java刚一解析前几个字符就已经报错了)。
ios:
+ (NSString *)encrypt:(NSString *)sText encryptOrDecrypt:(CCOperation)encryptOperation key:(NSString *)key{
const Byte iv[] = {1,2,3,4,5,6,7,8};
NSString *tempText = nil;
NSData *textData = [sText dataUsingEncoding:NSUTF8StringEncoding];
NSUInteger dataLength = [textData length];
unsigned char buffer[1024];
memset(buffer, 0, sizeof(char));
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmDES,
kCCOptionPKCS7Padding,
[key UTF8String], kCCKeySizeDES,
iv,
[textData bytes], dataLength,
buffer, 1024,
&numBytesEncrypted);
if (cryptStatus == kCCSuccess) {
NSData *data = [NSData dataWithBytes:buffer length:(NSUInteger)numBytesEncrypted];
// ciphertext = [GTMBase64 encodehaha:data];
// ciphertext = [self parseByte2HexString:data];
tempText = [self parseByte2HexString:buffer];
tempText = [tempText uppercaseString];
NSLog(@"加密结果%@------%@",tempText, data);
}
return tempText;
}
+(NSString *) parseByte2HexString:(Byte *) bytes
{
NSMutableString *hexStr = [[NSMutableString alloc]init];
int i = 0;
if(bytes)
{
while (bytes[i] != '\0')
{
NSString *hexByte = [NSString stringWithFormat:@"%x",bytes[i] & 0xff];///16进制数
if([hexByte length]==1)
[hexStr appendFormat:@"0%@", hexByte];
else
[hexStr appendFormat:@"%@", hexByte];
i++;
}
}
NSLog(@"bytes 的16进制数为:%@",hexStr);
return hexStr;
}
//解密
+ (NSString *) decryptUseDES:(NSString*)cipherText key:(NSString*)key
{
NSData* temData = [GTMBase64 decodeString:cipherText];
unsigned char buffer[1024];
memset(buffer, 0, sizeof(char));
size_t numBytesDecrypted = 0;
Byte iv[] = {1,2,3,4,5,6,7,8};
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt,
kCCAlgorithmDES,
kCCOptionPKCS7Padding,
[key UTF8String],
kCCKeySizeDES,
iv,
[temData bytes],
[temData length],
buffer,
1024,
&numBytesDecrypted);
NSString* tempText = nil;
if (cryptStatus == kCCSuccess) {
NSData* data = [NSData dataWithBytes:buffer length:(NSUInteger)numBytesDecrypted];
tempText = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}
NSLog(@"解密的%@",tempText);
return tempText;
}
Java:
public static String encryptDES(String encryptString, String encryptKey) throws Exception {
SecretKeySpec key = new SecretKeySpec(encryptKey.getBytes(), "DES");
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encryptedData = cipher.doFinal(encryptString.getBytes());
return byte2hex(encryptedData);
}
public static void main(String[] args) throws Exception {
String source = "测试数据";
String aim = StringCrypUtil.encryptDES(source, "infoware");
System.out.println(aim);
}
private static String byte2hex(byte[] b) {
String hs = "";
String stmp = "";
for (int n = 0; n < b.length; n++) {
stmp = (java.lang.Integer.toHexString(b[n] & 0XFF));
if (stmp.length() == 1) {
hs = hs + "0" + stmp;
} else {
hs = hs + stmp;
}
}
return hs.toUpperCase();
}
到此终于调通了。
因为我们项目不需要base64加密,所以只需要把获取到的buffer做16进制以及大写处理,此时出现一个问题:采用PKCS7Padding或者PKCS5Padding这种加密方式,末端添加的数据可能不固定,在解码后需要把末端多余的字符去掉,比较棘手,现在发现有的设备加密是和java端一致的,有的设备会在末端加几位(至于是几这个随机)。 现在临时做法是只保留64位字符,然后传给服务端。为什么不base64编码呢,好蛋疼。继续找解决方法。