我在使用RC4算法(http://rc4crypt.devhome.org)
加密的服务器上有一个XML文件function encrypt ($pwd, $data, $ispwdHex = 0)
{
if ($ispwdHex)
$pwd = @pack('H*', $pwd); // valid input, please!
$key[] = '';
$box[] = '';
$cipher = '';
$pwd_length = strlen($pwd);
$data_length = strlen($data);
for ($i = 0; $i < 256; $i++)
{
$key[$i] = ord($pwd[$i % $pwd_length]);
$box[$i] = $i;
}
for ($j = $i = 0; $i < 256; $i++)
{
$j = ($j + $box[$i] + $key[$i]) % 256;
$tmp = $box[$i];
$box[$i] = $box[$j];
$box[$j] = $tmp;
}
for ($a = $j = $i = 0; $i < $data_length; $i++)
{
$a = ($a + 1) % 256;
$j = ($j + $box[$a]) % 256;
$tmp = $box[$a];
$box[$a] = $box[$j];
$box[$j] = $tmp;
$k = $box[(($box[$a] + $box[$j]) % 256)];
$cipher .= chr(ord($data[$i]) ^ $k);
}
return $cipher;
}
这是我用来解密的Objective-C代码:
NSData *dataToDecrypt = [NSURLConnection sendSynchronousRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.url.com/fileCrypted.xml"]] returningResponse:nil error:nil];
const void *vplainText;
size_t plainTextBufferSize;
plainTextBufferSize = [dataToDecrypt length];
vplainText = [dataToDecrypt bytes];
CCCryptorStatus ccStatus;
uint8_t *bufferPtr = NULL;
size_t bufferPtrSize = 0;
size_t movedBytes = 0;
bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1);
bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));
memset((void *)bufferPtr, 0x0, bufferPtrSize);
NSString *key = @"mykey";
//NSString *initVec = @"init Vec";
const void *vkey = (const void *) [key UTF8String];
const void *vinitVec = (const void *) [initVec UTF8String];
size_t keyLength = [[key dataUsingEncoding:NSUTF8StringEncoding] length];
ccStatus = CCCrypt(kCCDecrypt,
kCCAlgorithmRC4,
0,
vkey,
kCCKeySizeDES,
nil,
vplainText,
plainTextBufferSize,
(void *)bufferPtr,
bufferPtrSize,
&movedBytes);
if (ccStatus == kCCSuccess) NSLog(@"SUCCESS");
/*else*/ if (ccStatus == kCCParamError) return @"PARAM ERROR";
else if (ccStatus == kCCBufferTooSmall) return @"BUFFER TOO SMALL";
else if (ccStatus == kCCMemoryFailure) return @"MEMORY FAILURE";
else if (ccStatus == kCCAlignmentError) return @"ALIGNMENT";
else if (ccStatus == kCCDecodeError) return @"DECODE ERROR";
else if (ccStatus == kCCUnimplemented) return @"UNIMPLEMENTED";
NSString *result = [[ NSString alloc ] initWithData: [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes] encoding:NSASCIIEncoding];
日志输出:SUCCESS但我的结果不好(我测试了很多编码,但ASCII似乎是好的,参见PHP函数ord ...)
我的两个RC4实施标准是什么?
编辑:在Objective-C代码中删除了IV Edit2:Objective-C KeyLength =密码数据长度,删除选项
答案 0 :(得分:3)
如果您不知道自己在加密方面所做的工作,那么“滚动自己”就是灾难的必要条件。你不必相信我,在The Cult of Schneier上阅读John Viega,了解那些试图“推出自己的”密码学的普通程序员。转述:不要这样做。
由于这是一个文件,我猜一个合理的小文件,你可以使用更多标准和更高级别的库,使用SSL(OpenSSL等)或OpenPGP(GPG等)等标准来做必要的加密/解密。我相信在Objective-C(或iPhone环境)和PHP中都有SSL的库或模块支持。
特别是关于RC4,它是一个流密码,编写起来很简单,但令人难以置信的是它的实现细节容易搞乱。有关众所周知的历史案例,请参阅The Misuse of RC4 in Microsoft Word and Excel和Can you recommend RC4 128-bit encrypted software?,以及安全/加密专家(前CTO和PGP公司联合创始人)的推荐。
<强>加了:强>
php脚本中的密钥大小基于密码数据的原始长度。它也没有使用任何PKCS7 Padding,所以我认为该字段应该为零(0)(CCryptor不支持流密码的填充,并且php版本肯定不使用它)。在你的代码中,CCCrypt使用了8字节(64 *位)的密钥,但我相信你希望它是密码的长度(以字节为单位)(二进制数据)。
数据没有MAC或散列,因此函数无法从无效解码中确定有效。
我认为这将使您更接近与RC4的这种不安全的实现(PHP中的RC4crypt)的兼容性。
答案 1 :(得分:1)
在@mctylr的基础上,尽可能避免自己滚动。如果您需要RC4,请使用预先构建/测试的库:OpenSSL RC4。您可以用大约3行替换整个代码。