terl / lazysodium-java

A Java implementation of the Libsodium crypto library. For the lazy dev.
https://github.com/terl/lazysodium-java/wiki
Mozilla Public License 2.0
136 stars 49 forks source link

BLAKE2b-256 #33

Closed xianaofei closed 6 years ago

xianaofei commented 6 years ago

hashPrevouts: BLAKE2b-256('ZcashPrevoutHash',b'') = d53a633bbecf82fe9e9484d8a0e727c73bb9e68c96e72dec30144f6a84afa136 How to write this project, thank you @gurpreet-

gurpreet- commented 6 years ago

Hi @xianaofei

I think you want to perform a Blake2B hash? If so, then yes, you can perform a Blake2B 256-bit hash using Lazysodium.

The code would be something like:

// Create key for the hash
String key = lazySodium.cryptoGenericHashKeygen();

// Create the hash
String hash = lazySodium.cryptoGenericHash("message to hash", key);

// hash = 45456331212f82fe9e9ba4d8a0e727c73bb9e68c96e72dec30144faed231345
// Now you can store the hash somewhere.

Hope that answers your question?

xianaofei commented 6 years ago

hi BLAKE2b-256('ZcashPrevoutHash','') = d53a633bbecf82fe9e9484d8a0e727c73bb9e68c96e72dec30144f6a84afa136

Use ZcashPrevoutHash as key, message is "". Output d53a633bbecf82fe9e9484d8a0e727c73bb9e68c96e72dec30144f6a84afa136

String hash = lazySodium.cryptoGenericHash("", "ZcashPrevoutHash"); But I use it The output values are not the same

gurpreet- commented 6 years ago

Please see the examples project. In particular, please look at this function which demonstrates lazySodium.genericHash(...) and that it does produce the same output values 👍

Does that help?

xianaofei commented 6 years ago

https://github.com/jedisct1/libsodium/tree/master/src/libsodium This is the algorithm used by ZEC to encrypt digital money

String hash = lazySodium.cryptoGenericHash("", “ZcashPrevoutHash”); String hash2 = lazySodium.cryptoGenericHash("", “ZcashPrevoutHash”); Output value A2C1AE1F0169A7B973A8CCF7A563544377366897D8485B4173E461DE5859B2D8 A2C1AE1F0169A7B973A8CCF7A563544377366897D8485B4173E461DE5859B2D8 != d53a633bbecf82fe9e9484d8a0e727c73bb9e68c96e72dec30144f6a84afa136

I am very puzzled about this algorithm. I am a beginner. Thank you for your support. Need BLAKE2b-256 algorithm.Is that so?

xianaofei commented 6 years ago

python h = hashlib.blake2b(person=b'ZcashOutputsHash', digest_size=32) h.update(binascii.unhexlify(b'8f739811893e0000095200ac6551ac636565b1a45a0805750200025151')) print(h.hexdigest())

ec55f4afc6cebfe1c35bdcded7519ff6efb381ab1d5a8dd0060c13b2a512932b

java Blake2b mac = Blake2b.Mac.newInstance("ZcashPrevoutHash".getBytes(), 32); mac.update("".getBytes()); tmp = mac.digest(); System.out.println("end..." + toHexString(tmp)); out 8cfa9d64e689eb8447f1080d81f4ca37be863e780f6875b69b1a51df589c2201 ec55f4afc6cebfe1c35bdcded7519ff6efb381ab1d5a8dd0060c13b2a512932b != 8cfa9d64e689eb8447f1080d81f4ca37be863e780f6875b69b1a51df589c2201

mac.update("".getBytes()); Is there a problem here and how to use it? Thank you. https://github.com/alphazero/Blake2b

gurpreet- commented 6 years ago

Oh I understand what you mean now. You want the result of cryptoGenericHash to actually equal d53a633bbecf82fe9e9484d8a0e727c73bb9e68c96e72dec30144f6a84afa136. I also see that you want to use it in zcash.

I did some research1 and think that zcash is using the crypto_generichash_blake2b_salt_personal method rather than the plain crypto_generichash method.

So the following should work...

// We don't really need these
byte[] message = lazySodium.bytes("");
byte[] keyBytes = lazySodium.bytes("");

byte[] hash = lazySodium.randomBytesBuf(GenericHash.BYTES);

// We have to drop down to the native Sodium implementation
// for this so we get it via lazySodium.getSodium()
lazySodium.getSodium().crypto_generichash_blake2b_salt_personal(
            hash,
            hash.length,
            message,
            message.length,
            keyBytes,
            keyBytes.length,
            0L,
            lazySodium.bytes("ZcashPrevoutHash")
);

System.out.println(lazySodium.sodiumBin2Hex(hash)); 
// D53A633BBECF82FE9E9484D8A0E727C73BB9E68C96E72DEC30144F6A84AFA136
  1. https://github.com/zcash/zcash/issues/3382. I saw that the person in this issue was using the personal parameter rather than the key parameter to input ZcashOutputsHash. Thus, it led me to look for the crypto_generichash_blake2b_salt_personal method.
xianaofei commented 6 years ago

There are 3 test cases. The first 2 work with lazysodium, but the last one errors...

// Test case 1 works
hashPrevouts:
  BLAKE2b-256('ZcashPrevoutHash', b'')
= d53a633bbecf82fe9e9484d8a0e727c73bb9e68c96e72dec30144f6a84afa136
// Test case 2 works
hashSequence:
  BLAKE2b-256('ZcashSequencHash', b'')
= a5f25f01959361ee6eb56a7401210ee268226f6ce764a4f10b7f29e54db37272
// Test case 3 fails
hashOutputs:
  BLAKE2b-256('ZcashOutputsHash', 8f739811893e0000095200ac6551ac636565b1a45a0805750200025151)
= ec55f4afc6cebfe1c35bdcded7519ff6efb381ab1d5a8dd0060c13b2a512932b

The code I wrote is as follows:

byte[] message = lazySodium.bytes("8f739811893e0000095200ac6551ac636565b1a45a0805750200025151");
byte[] keyBytes = lazySodium.bytes("");
byte[] hash = lazySodium.randomBytesBuf(GenericHash.BYTES);
lazySodium.getSodium().crypto_generichash_blake2b_salt_personal(
                hash,
                hash.length,
                message,
                message.length,
                keyBytes,
                keyBytes.length,
                0L,
                lazySodium.bytes("ZcashOutputsHash")
);
System.out.println(lazySodium.sodiumBin2Hex(hash));
// Prints D4EDCC04C5147D7911C78EE8325165265417152F973C707709E3E5246545989C which is incorrect

Is lazySodium.bytes("8f739811893e0000095200ac6551ac636565b1a45a0805750200025151"); correct? Does it need a special character conversion?

xianaofei commented 6 years ago

---success---I added 16 to binary conversion to binary ---byte[] message = toBytes("8f739811893e0000095200ac6551ac636565b1a45a0805750200025151") public static byte[] toBytes(String str) { if(str == null || str.trim().equals("")) { return new byte[0]; } byte[] bytes = new byte[str.length() / 2]; for(int i = 0; i < str.length() / 2; i++) { String subStr = str.substring(i 2, i 2 + 2); bytes[i] = (byte) Integer.parseInt(subStr, 16); } return bytes; }

xianaofei commented 6 years ago

@gurpreet- Thank you very much.

gurpreet- commented 6 years ago

Looking at https://github.com/zcash/zcash/issues/3382 again, I can see that you have to convert the hexadecimal string 8f739811893e0000095200ac6551ac636565b1a45a0805750200025151 to bytes first and then perform the operation.

So in order to get it working:

// Convert to hex first
byte[] message = lazySodium.sodiumHex2Bin("8f739811893e0000095200ac6551ac636565b1a45a0805750200025151");
byte[] keyBytes = lazySodium.bytes("");

byte[] hash = lazySodium.randomBytesBuf(GenericHash.BYTES);

lazySodium.getSodium().crypto_generichash_blake2b_salt_personal(
            hash,
            hash.length,
            message,
            message.length,
            keyBytes,
            keyBytes.length,
            0L,
            lazySodium.bytes("ZcashOutputsHash")
);

System.out.println(lazySodium.sodiumBin2Hex(hash));
// Prints EC55F4AFC6CEBFE1C35BDCDED7519FF6EFB381AB1D5A8DD0060C13B2A512932B
gurpreet- commented 6 years ago

Ah you beat me to it haha! Well, good luck!