From d85719b5a79c43899a2a71dba80fc336ba98607b Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 30 Jun 2016 12:08:27 -0700 Subject: [PATCH] lnwallet: add elkrem root derivation function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The derivation is current bed on an HKDF invocation using our private key as the secret, and the node’s channel multi-sig key as the salt. This scheme allows us to derive the key on the fly given data known to only us and the remote node. The current derivation is just a place-holder and will be re-visited at a later time. --- lnwallet/script_utils.go | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/lnwallet/script_utils.go b/lnwallet/script_utils.go index 0626daa1..0ab51d36 100644 --- a/lnwallet/script_utils.go +++ b/lnwallet/script_utils.go @@ -2,9 +2,12 @@ package lnwallet import ( "bytes" + "crypto/sha256" "fmt" "math/big" + "golang.org/x/crypto/hkdf" + "github.com/btcsuite/fastsha256" "github.com/roasbeef/btcd/btcec" "github.com/roasbeef/btcd/txscript" @@ -345,6 +348,7 @@ func senderHtlcSpendTimeout(commitScript []byte, outputAmt btcutil.Amount, // OP_ENDIF // OP_CHECKSIG // OP_ENDIF +// TODO(roasbeef): rename these to sender vs receiver? func receiverHTLCScript(absoluteTimeout, relativeTimeout uint32, senderKey, receiverKey *btcec.PublicKey, revokeHash, paymentHash []byte) ([]byte, error) { @@ -707,7 +711,7 @@ func deriveRevocationPubkey(commitPubKey *btcec.PublicKey, // a previously revoked commitment transaction. // // The private key is derived as follwos: -// revokePriv := commitPriv + revokePrimge mod N +// revokePriv := commitPriv + revokePreimage mod N // // Where N is the order of the sub-group. func deriveRevocationPrivKey(commitPrivKey *btcec.PrivateKey, @@ -730,3 +734,29 @@ func deriveRevocationPrivKey(commitPrivKey *btcec.PrivateKey, privRevoke, _ := btcec.PrivKeyFromBytes(btcec.S256(), revokePriv.Bytes()) return privRevoke } + +// deriveElkremRoot derives an elkrem root unique to a channel given the +// private key for our public key in the 2-of-2 multi-sig, and the remote +// node's multi-sig public key. The root is derived using the HKDF[1][2] +// instantiated with sha-256. The secret data used is our multi-sig private +// key, with the salt being the remote node's public key. +// +// [1]: https://eprint.iacr.org/2010/264.pdf +// [2]: https://tools.ietf.org/html/rfc5869 +func deriveElkremRoot(localMultiSigKey *btcec.PrivateKey, + remoteMultiSigKey *btcec.PublicKey) wire.ShaHash { + + secret := localMultiSigKey.Serialize() + salt := remoteMultiSigKey.SerializeCompressed() + info := []byte("elkrem") + + rootReader := hkdf.New(sha256.New, secret, salt, info) + + // It's safe to ignore the error her as we know for sure that we won't + // be draining the HKDF past its available entropy horizon. + // TODO(roasbeef): revisit... + var elkremRoot wire.ShaHash + rootReader.Read(elkremRoot[:]) + + return elkremRoot +}