Closed yojoe closed 3 years ago
Also to consider / evaluate: Is the argument for HMAC still strong enough? One of the arguments for HMAC was: public key serialization can be avoided; which is gone now. We're left with (better) resistance to length extension attacks and no nonce needed. But those points could be addressed differently without using HMAC, right? At least this seemed to be an option during the Milan workshop. I don't have an opinion here right now, because I'm missing a visual/spec of the alternatives that were up for discussion.
I restored the previous numbering and added a rationale section. While writing this, I became concerned we're using HMAC in a wrong way. According to Wikipedia on HMAC#Security:
The cryptographic strength of the HMAC depends upon the size of the secret key that is used. The most common attack against HMACs is brute force to uncover the secret key.
We use the public key S
as the secret key
and argue it provides sufficient entropy. This might be true for the first commitment to a public key, but once the commitment is revealed to another party for verification, the public key is no longer secret
or entropy
. Can we guarantee that the same public key is not used for subsequent commitments again? If not, we would open a potential attack vector for length extension attacks on HMAC in some cases, wouldn't we?
Seems like Wikipedia article in the cited two sentences mixes different topics and security assumptions.
The first sentence talks about the size of the HMAC secret key in contect of the collision attack. We already use the longest possible key, so are well protected from collision attacks. The fact that the key is known does not affect this assumption.
The second sentence talks about ability to create a HMAC authorized message by a party which is not the original holder of the secret. It is not about the length extension attack, it is about attack on message authenticity. However this does not apply to our situation, since we base the authenticity on the fact of the Secp256k1 public key participation in the bitcoin transaction, i.e. if somebody will create HMAC authorized message with the same public key (used as HMAC key) it will not change anything in the context of LNPBP-1 (and will not be an valid attack vector).
In terms of message length extension, HMAC algorithm does not allow to extend the length of the message and create a new HMAC value when the original message is not known even if the key is known. The length extension attack may happen during commitment procedure, not reveal/verify, for instance by a malicious software running on the client machine modifying the the commitment on the go. With HMAC this can be achieved only if the software will have access to the original message AND the key, and not only the key and the hash, while with SHA it is possible weithout any knowledge of the message and the key.
@yojoe and, BTW, bcb9aacb6d0fc9f491089fdf00b1d3b61e2290fa. Feel free to fix it with real name etc.
As raised in https://github.com/LNP-BP/LNPBPs/issues/108, LNPBP-1 must explicitly specify the serialization format for the public key (aggregated public key
S
), which is passed into SHA256-HMAC to compute the tweaking factor.TBD:
key.serialize_uncompressed()
fromrust-secp256k1
, this produces a 65 byte array - not 64 byte as assumed by @dr-orlovsky because of the0x04
prefix to denote uncompressed format. 65 byte means HMAC-SHA256 internals first compute a hash (sha256) again. Is this an issue? Could this introduce another length extension attack vector? Do we need to prepend two 32 byte tags as we do elsewhere?0x04
prefix for public key serialization in LNPBP-1. But this would be "uncommon", it would be a derivation from the defacto standard for uncompressed public keys. Would that be an issue? Create confusion?rust-secp256k1
rust-secp256k1
key.serialize_uncompressed()
, but strip the first byte afterwards, before pushing the value into HMAC-SHA256. The question is ifserialize_uncompressed()
can be considered "stable" in a sense that the format of the resulting value will never change and always stay like it is now?rust-secp256k1
functionkey.serialize()
, most (all) of the test vectors inAppendix A
change and need to be re-computed and changed in the spec (ideally before merging). I'm not a RUST dev and have no dev environment setup ready to do this. @dr-orlovsky can you help?