I am trying to generate LSAG KeyImage by myself in C which is K̃ = kπ*Hp(R).

And I take result of MiniNero as a reference..

def test_keyImage():
    private_key = "907cf0eb0e0bbd761a7ed9bc8777fa5530e8262792a3e718533a1a357a1e4199"
    public_keys = "a9931c8d70237a279b8d3181f947830f0c3a21032d22b5d6e81c3afeba51bb0c", "210330a31c3caab4087c19fbe770514e5e6b80eda552d1e5f8becabd12c4540e","824ec9615ece05e6f5707facd88abbfb79b32f97b6a68be5304b5b2dfc06df01"
    public_join = ''.join(pub)
    hashpj = MiniNero.cn_fast_hash(public_join)

    HR = MiniNero.hashToPointCN(hashpj)

The result:

HR:    996b4d50ed204c7f14b106c818a7268a9cd66166ff194e13beefb6880c8aac39

As code above, I join 3 public keys to form R and run with cn_fast_hash(), then using hashToPointCN() to get HR. However, can not get the same value from my C code implement.

ge_p2 point;
ge_p1p1 point2;
ge_p3 point3;

uint8_t hash_result[32];
uint8_t final_res[32];

keccak(pub_keys, 96, hash_result, 32); //keccak(PSK, 32, result, 32);

for(i=0; i<32; i++){
    printf("%02x", hash_result[i]);}

ge_fromfe_frombytes_vartime(&point, hash_result);
ge_mul8(&point2, &point);
ge_p1p1_to_p3(&point3, &point2);
ge_p3_tobytes(final_res, &point3);

for(i=0; i<32; i++)
    printf("%02x", final_res[i]);

The result:


From the result, we can see that keccak hash is right, but I can not get the same result as what MiniNero.hashToPointCN() does.

Please help me on this problem, I am lost here...

1 Answer 1


Your tests are not the same.

If you look at the source for hashToPointCN, you will see:

def hashToPointCN(hexVal):
    u= hexToInt(cn_fast_hash(hexVal)) % q

It hashes the input.

So in your Python test, you are outputting the result of cn_fast_hash, which is being used as input to hashToPointCN, which is hashing again and then returning a result point.

Your C test is correct in that you are only hashing the input once.

Thus, if you amended your Python to:

HR = MiniNero.hashToPointCN(public_join)

You'd get the same result as the C version:


As an FYI, you can see exactly how a key image is generated in the source code of Monero here: src/crypto/crypto.cpp#L481-L498

  • BTW, I notice it's different between keyImage(x) in LLW_Sigs.py with keyImageV(x) in MLSAG2.py. The first one uses hashToPoint_ct and the second one uses hashToPointCN. May I know which one is right?
    – Mooooo
    Commented Apr 15, 2020 at 14:10
  • As I just tested with monero-project/tests/crypto/test.txt I found the test data match result of using hashToPointCN. Is it true?
    – Mooooo
    Commented Apr 15, 2020 at 14:28
  • I saw the comment. #a simple hash function I was using to test C.T. stuff #for the actual one, see the function just previous to this Thank you!
    – Mooooo
    Commented Apr 15, 2020 at 14:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.