Porting C# CryptoSys-assisted 3DES encryption to Objective-C CommonCrypto issues -
i working on iphone app port of subset of .net c# functionality. must log server using 3des encrypted password (yes, know not optimal standard, please bear me).
so far, however, no joy. cannot replicate encryption in c# code. code in both c# in objective-c shares these common variables:
strpasswordunencrypted password, "secret"abplainbyte array hex values of strpassword{73, 65, 63, 72, 65, 74, 02, 02}rpmpasswordstring of random characters.rpmpasswordasdataobjective-c representation of rpmpassword nsdata using utf8 encodingabpasswordbyte array values of rpmpassword- i've added code derive
nlenin objective-c code below
here's c# code first:
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]; (int = 0; < blockbytes; i++) aboutput[i] = abinitv[i]; (int = 0; < nlen + npad; i++) aboutput[blockbytes + i] = abcipher[i]; return cryptosysapi.cnv.tohex(aboutput) as can see, encrypted value returns concatenation of hex values of abinitv , abcipher.
i have been cribbing rob napier try , transform working objective-c code, far, it's not happening. producing abinitv , abcipher values of right length, , i'm concatenating them aboutput, being rejected server when try log in.
here's objective-c code (the constants declared, promise):
int nlen = [strpassword length]; int npad = ((nlen / blockbytes) + 1) * blockbytes - nlen; nsdata *abinitv = [self randomdataoflength:blockbytes]; // salthex 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]; (int = 0; < blockbytes; i++) { [aboutput replacebytesinrange:nsmakerange(i, sizeof(abinitvasbytes[i])) withbytes:&abinitvasbytes[i]]; } (int = 0; < nlen + npad; i++) { [aboutput replacebytesinrange:nsmakerange(blockbytes + i, sizeof(abcipherasbytes[i])) withbytes:&abcipherasbytes[i]]; } return [encryptionutil nsdatatohex:aboutput]; and here supporting methods called in code above:
+(nsstring*) nsdatatohex:(nsdata*)data { const unsigned char *dbytes = [data bytes]; nsmutablestring *hexstr = [nsmutablestring stringwithcapacity:[data length]*2]; int i; (i = 0; < [data length]; i++) { [hexstr appendformat:@"%02x ", dbytes[i]]; } return [nsstring stringwithstring: hexstr]; } +(nsdata*)hextonsdata:(nsstring*)hex { nsmutabledata* data = [nsmutabledata data]; int idx; (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 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; } so, if can tell me i'm doing wrong, i'd sincerely appreciate it. if had hazard guess, i'd assume problem in 1 of 2 places:
- generating key, either in call to, or code of
tdeakeyforpassword - calling
cccrypt.
that said, i've tried every available prf constant, padding , no padding.
i'm inexperienced encryption, i'd appreciate can offer.
thanks!
first, code samples seem different. c# code encrypting abplain. objc code encrypting abpassword. indicate abplain static, while abpassword random. have kind of padding going on in objc don't see in c# (maybe 0 padding? that's not standard way pad.)
if remove randomness, each implementation should return same result same input. first, hard-code random value (i use 0, random other number), , choose common abpassword. then, @ each step of process, make sure both implementations generate same result. significantly, abkey same, , abcipher, , aboutput. @ 1 of these points implementations diverge. (from quick reading, seem doing different things along.)
one thing confusing how switch between abpassword , rpmpassword. in 1 case pass abpassword, length of rpmpasswordasdata. feels place it's easy make mistake.
the length of abpassword unclear. assume it's multiple of 8, or else ccnopadding going blow up.
nsmutabledata has appenddata method. that's easier replacebytesinrange:…
Comments
Post a Comment