【发布时间】:2013-05-04 14:20:03
【问题描述】:
我目前正在开发一个 iPhone 应用程序,它是 .NET C# 功能子集的一个端口。我必须使用 3DES 加密密码登录服务器(是的,我知道这不是最佳标准,但请多多包涵)。
然而,到目前为止,还没有快乐。我无法正确复制此 C# 代码中的加密。 Objective-c 中的两个 C# 中的代码共享这些公共变量:
-
strPassword是未加密的密码,如“secret” -
abPlain是一个字节数组,其十六进制值为 strPassword{73, 65, 63, 72, 65, 74, 02, 02} -
rpmPassword是一串随机字符。 -
rpmPasswordAsData是 rpmPassword 使用 UTF8 编码的 NSData 的唯一 Objective-C 表示 -
abPassword是一个字节数组,其值为 rpmPassword - 我在下面的 Objective-C 代码中添加了派生
nLen的代码
首先是 C# 代码:
static int ITERATIONCOUNT = 2048;
static int KEYBYTES = 24;
static int BLOCKBYTES = 8;
byte[] abInitV = CryptoSysAPI.Rng.NonceBytes(BLOCKBYTES);
byte[] abKey = CryptoSysAPI.Pbe.Kdf2(KEYBYTES, abPassword, abInitV, ITERATIONCOUNT);
CryptoSysAPI.Tdea cipher = CryptoSysAPI.Tdea.Instance();
cipher.InitEncrypt(abKey, Mode.CBC, abInitV);
byte[] abCipher = cipher.Update(abPlain);
abOutput = new byte[abCipher.Length + BLOCKBYTES];
for (int i = 0; i < BLOCKBYTES; i++) abOutput[i] = abInitV[i];
for (int i = 0; i < nLen + nPad; i++) abOutput[BLOCKBYTES + i] = abCipher[i];
return CryptoSysAPI.Cnv.ToHex(abOutput)
如您所见,它返回的加密值实际上是abInitV 和abCipher 的十六进制值的串联。
我一直从 Rob Napier 那里抄袭,试图将其转换为可工作的 Objective-c 代码,但到目前为止,还没有发生。我正在生成正确长度的abInitV 和abCipher 值,并且我还将它们正确连接到abOutput,但是当我尝试登录时被服务器拒绝。
这是我的 Objective-c 代码(我保证也声明了常量):
int nLen = [strPassword length];
int nPad = ((nLen / BLOCKBYTES) + 1) * BLOCKBYTES - nLen;
NSData *abInitV = [self randomDataOfLength:BLOCKBYTES]; // This is the salthex for the encryption
const unsigned char *abInitVAsBytes = [abInitV bytes];
NSData *abKey = [self TDEAKeyForPassword:strPassword salt:abInitV];
size_t movedBytes = 0;
NSMutableData *abCipher = [NSMutableData dataWithLength:BLOCKBYTES];
CCCryptorStatus result = CCCrypt(kCCEncrypt,
kCCAlgorithm3DES,
ccNoPadding & kCCModeCBC,
[abKey bytes],
kCCKeySize3DES,
[abInitV bytes],
abPassword,
[rpmPasswordAsData length],
abCipher.mutableBytes,
KEYBYTES,
&movedBytes);
if (result == kCCSuccess)
{
NSLog(@"abCipher == %@ \n", [abCipher description] );
}
NSMutableData *abOutput = [NSMutableData dataWithCapacity:[abCipher length] + BLOCKBYTES];
const unsigned char *abCipherAsBytes = [abCipher bytes];
for (int i = 0; i < BLOCKBYTES; i++)
{
[abOutput replaceBytesInRange:NSMakeRange(i, sizeof(abInitVAsBytes[i])) withBytes:&abInitVAsBytes[i]];
}
for (int i = 0; i < nLen + nPad; i++)
{
[abOutput replaceBytesInRange:NSMakeRange(BLOCKBYTES + i, sizeof(abCipherAsBytes[i])) withBytes:&abCipherAsBytes[i]];
}
return [EncryptionUtil NSDataToHex:abOutput];
下面是上面代码中调用的支持方法:
+(NSString*) NSDataToHex:(NSData*)data
{
const unsigned char *dbytes = [data bytes];
NSMutableString *hexStr =
[NSMutableString stringWithCapacity:[data length]*2];
int i;
for (i = 0; i < [data length]; i++) {
[hexStr appendFormat:@"%02x ", dbytes[i]];
}
return [NSString stringWithString: hexStr];
}
+(NSData*)HexToNSData:(NSString*)hex
{
NSMutableData* data = [NSMutableData data];
int idx;
for (idx = 0; idx+2 <= [hex length]; idx+=2) {
NSRange range = NSMakeRange(idx, 2);
NSString* hexStr = [hex substringWithRange:range];
NSScanner* scanner = [NSScanner scannerWithString:hexStr];
unsigned int intValue;
[scanner scanHexInt:&intValue];
[data appendBytes:&intValue length:1];
}
return data;
}
+(NSData *)randomDataOfLength:(size_t)length
{
NSMutableData *data = [NSMutableData dataWithLength:length];
int result = SecRandomCopyBytes(kSecRandomDefault,
length,
data.mutableBytes);
NSAssert(result == 0, @"Unable to generate random bytes: %d",
errno);
return data;
}
+(NSData *)TDEAKeyForPassword:(NSString *)password
salt:(NSData *)salt
{
NSMutableData *
derivedKey = [NSMutableData dataWithLength:kCCKeySize3DES];
int result = CCKeyDerivationPBKDF(kCCPBKDF2, // algorithm
password.UTF8String, // password
password.length, // passwordLength
salt.bytes, // salt
salt.length, // saltLen
kCCPRFHmacAlgSHA1, // PRF
ITERATIONCOUNT, // rounds
derivedKey.mutableBytes, // derivedKey
derivedKey.length); // derivedKeyLen
return derivedKey;
}
所以,如果有人能告诉我我做错了什么,我将不胜感激。如果我不得不冒险猜测,我会假设问题出在以下两个地方之一:
- 在
TDEAKeyForPassword的调用或代码中生成密钥 - 致电
CCCrypt。
也就是说,我已经尝试了所有可用的 PRF 常量,以及填充和无填充。
我对加密非常缺乏经验,所以如果有人能提供任何帮助,我将不胜感激。
谢谢!
【问题讨论】:
-
什么是
npad?strPassword是什么?abPassword是什么?rpmPasswordAsData是什么? -
对不起,特鲁迪斯兄弟。我的错。我在上面添加了详细信息。
标签: c# objective-c encryption 3des