android - Java vs Python HMAC-SHA256 Mismatch -
based on recent feedback , findings on problem, i've rewritten question rid of noise.
i have 2 separate code paths, 1 in java (android), 1 , python accomplish following purposes of negotiating pairing between android device , python/django.
java:
- generate synckey
- hash concatenated string of various values using presharedkey (including synckey)
- encrypt synckey using presharedkey
- send hash, encrypted synckey, deviceid , arbitrary variables web server
python
- get presharedkey deviceid
- decrypt encrypted synckey
- hash concatenated string of various values using presharedkey (including decrypted synckey)
- make sure hash matches, confirms synckey decrypted successfully, , deviceid holds correct presharedkey.
now process works if send synckey unencrypted. final hash matches, proves deviceid has correct preshared-key, add en/decryption process, hash no longer matches, despite fact both synckey , concatenated string appear match character character debug output of both java/python.
one quirk of process 256bit key necessary aes256 encryption algorithm, i'm chopping 512bit presharedkey in half. alternative of using 256bit key across board requiring pass key through encode('ascii')
on python side, or else throwing errors during hashing shorter key.
here relevant code:
java:
string presharedkey = getkey(); // f8250b0d5960444e4de6ecc3a78900bb941246a1dece7848fc72b90092ab3ecd0c1c8e36fddba501ef92e72c95b47e07f98f7fd9cb63da75c008a3201124ea5d string deviceid = getdeviceid(); // 1605788742789230 synckey synckey = generatesynckey(); // 824c1ee9ef507b52ea28362c71bd4ad512a5f82acfae80def531f73ac124ca814ba30ce805a157d6adb9ec04fc99aae6fdc4238fcd76b87ce22bc2fe33b2e5c9 string concat = synckey.hexstring(); // 824c1ee9ef507b52ea28362c71bd4ad512a5f82acfae80def531f73ac124ca814ba30ce805a157d6adb9ec04fc99aae6fdc4238fcd76b87ce22bc2fe33b2e5c9 string algorithm = "hmacsha256"; string hash = null; try { secretkeyspec keyspec = new secretkeyspec( presharedkey.getbytes(), algorithm); mac mac = mac.getinstance(algorithm); mac.init(keyspec); byte[] result = mac.dofinal(concat.getbytes()); hash = base64.encodetostring(result, base64.default); // fpde2jlmcbr+/rw+n/jbhh13f8av80sum2fqay2iprs= } catch (nosuchalgorithmexception x) { } catch (invalidkeyexception x) { } string enckey = presharedkey.substring(0, presharedkey.length() / 2); // f8250b0d5960444e4de6ecc3a78900bb941246a1dece7848fc72b90092ab3ecd int len = enckey.length(); byte[] enckeybytes = new byte[len / 2]; (int = 0; < len; += 2) { enckeybytes[i / 2] = (byte) ((character.digit(enckey.charat(i), 16) << 4) + character.digit(enckey.charat(i+1), 16)); } string encryptedsynckey = null; try { byte[] iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; algorithmparameterspec ivspec = new ivparameterspec(iv); secretkeyspec enckeyspec = new secretkeyspec(enckeybytes, "aes"); cipher cipher = cipher.getinstance("aes/cbc/pkcs5padding"); cipher.init(cipher.encrypt_mode, enckeyspec, ivspec); byte[] encryptedsynckeybytes = cipher.dofinal(synckey.hexstring().getbytes()); encryptedsynckey = base64.encodetostring(encryptedsynckeybytes, base64.default); /* yrl0/sutuutc6oj8o4tcoy65ewo0jzoxfei9klq0aolf6rh+nn7+bec0s5ue7tio1uljb/dvr2ca acmqvxxhgpzutb4sq0eso+t32lg0eeb9xki5cz4l9qo5raw0xbn7r/tfidvm8aifkn9qccths0df kh3owhpwns+tfeuiblpggqp/zgtozmido9u9lb4n */ } catch (invalidalgorithmparameterexception e) { } catch (nosuchalgorithmexception e) { } catch (nosuchpaddingexception e) { } catch (invalidkeyexception e) { } catch (illegalblocksizeexception e) { } catch (badpaddingexception e) { } sendstufftoweb(encryptedsynckey, deviceid, hash);
python:
hash = gethash(request) # hash java: fpde2jlmcbr+/rw+n/jbhh13f8av80sum2fqay2iprs= encrypted_sync_key = getencsynckey(request) # encryptedsynckey java: # yrl0/sutuutc6oj8o4tcoy65ewo0jzoxfei9klq0aolf6rh+nn7+bec0s5ue7tio1uljb/dvr2ca # acmqvxxhgpzutb4sq0eso+t32lg0eeb9xki5cz4l9qo5raw0xbn7r/tfidvm8aifkn9qccths0df # kh3owhpwns+tfeuiblpggqp/zgtozmido9u9lb4n device_id = getdeviceid(request) # 1605788742789230 preshared_key = getpresharedkeyfromdevice(deviceid) # f8250b0d5960444e4de6ecc3a78900bb941246a1dece7848fc72b90092ab3ecd0c1c8e36fddba501ef92e72c95b47e07f98f7fd9cb63da75c008a3201124ea5d enc_key = preshared_key[:len(preshared_key)/2] # f8250b0d5960444e4de6ecc3a78900bb941246a1dece7848fc72b90092ab3ecd aes = aes.new(enc_key.decode('hex'), aes.mode_cbc, iv="\x00"*16) sync_key = aes.decrypt(base64.b64decode(encrypted_sync_key)) # 824c1ee9ef507b52ea28362c71bd4ad512a5f82acfae80def531f73ac124ca814ba30ce805a157d6adb9ec04fc99aae6fdc4238fcd76b87ce22bc2fe33b2e5c9 concat = sync_key # 824c1ee9ef507b52ea28362c71bd4ad512a5f82acfae80def531f73ac124ca814ba30ce805a157d6adb9ec04fc99aae6fdc4238fcd76b87ce22bc2fe33b2e5c9 import hashlib hmac import new hmac verify_hash = hmac(preshared_key, concat, hashlib.sha256).digest().encode('base64') # iosc2w2sq4/fwhjtduqhw/hdyjy+ranzq1z3j5lfyba=
from debug output below can see synckey
encrypted , decrypted successfully, , concat
identical. resulting hash
ends being different.
your python code wrong. can reproduce, in python, answer got in java.
if use inputs:
>>> preshared_key_hex b'f8250b0d5960444e4de6ecc3a78900bb941246a1dece7848fc72b90092ab3ecd0c1c8e36fddba501ef92e72c95b47e07f98f7fd9cb63da75c008a3201124ea5d' >>> concat_hex b'824c1ee9ef507b52ea28362c71bd4ad512a5f82acfae80def531f73ac124ca814ba30ce805a157d6adb9ec04fc99aae6fdc4238fcd76b87ce22bc2fe33b2e5c9'
i same value in java:
>>> base64.b64encode(hmac.new(preshared_key_hex, concat_hex, hashlib.sha256).digest()) b'fpde2jlmcbr+/rw+n/jbhh13f8av80sum2fqay2iprs='
however, value wrong. should hex decoding input values.
i'm unable reproduce got in python; 1 of values you're passing hmac.new
isn't think is. print
them before calling hmac.new
, should see doesn't match.
Comments
Post a Comment