3

私は現在、.NET C# 機能のサブセットのポートである iPhone アプリに取り組んでいます。3DES で暗号化されたパスワードを使用してサーバーにログインする必要があります (はい、これが最適な標準ではないことは承知していますが、ご容赦ください)。

しかし、これまでのところ、喜びはありません。この C# コードでは、暗号化を適切に複製できません。Objective-C の両方の C# のコードは、次の共通の変数を共有しています。

  1. strPassword「secret」などの暗号化されていないパスワードです。
  2. abPlainstrPassword の 16 進値を持つバイト配列です{73, 65, 63, 72, 65, 74, 02, 02}
  3. rpmPasswordランダムな文字列です。
  4. rpmPasswordAsDataUTF8 エンコーディングを使用した NSData としての rpmPassword の Objective-C のみの表現です。
  5. abPasswordrpmPassword の値を持つバイト配列です。
  6. nLen以下の目的の C コードで派生するコードを追加しました

最初の 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ご覧のとおり、これが返す暗号化された値は、実際にはとの 16 進値を連結したものabCipherです。

私は Rob Napier から、これを実用的な Objective-C コードに変換しようとしていますが、これまでのところ、それは起こっていません。私は適切な長さの値を生成しており、それらを適切に連結していますがabInitV、ログインしようとするとサーバーによって拒否されています.abCipherabOutput

これが私の客観的な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;
}

だから、誰かが私が間違っていることを教えてくれたら、心から感謝します。推測を危険にさらす必要がある場合、問題は次の2つの場所のいずれかにあると思います。

  1. の呼び出しまたはコードでのキーの生成TDEAKeyForPassword
  2. 呼び出しCCCryptます。

そうは言っても、利用可能なすべての PRF 定数と、パディングとパディングなしを試しました。

私は暗号化に非常に慣れていないので、誰かが提供できる助けをいただければ幸いです。

ありがとう!

4

1 に答える 1

0
于 2013-05-11T00:40:53.113 に答える