1
0
Fork 0
mirror of https://github.com/ACINQ/eclair.git synced 2025-02-22 14:22:39 +01:00

implement revocation key derivation

This commit is contained in:
sstone 2016-11-28 18:39:13 +01:00
parent 1fe8b8feb2
commit 4e29d2b9fe
2 changed files with 76 additions and 0 deletions

View file

@ -1,5 +1,7 @@
package fr.acinq.protos
import java.math.BigInteger
import fr.acinq.bitcoin._
import fr.acinq.eclair.channel.Scripts
@ -65,4 +67,56 @@ object Bolt3 {
OP_CHECKSIG :: Nil
// @formatter:on
}
def fixSize(data: BinaryData): BinaryData = data.length match {
case 32 => data
case length if length < 32 => Array.fill(32 - length)(0.toByte) ++ data
}
case class Scalar(data: BinaryData) {
require(data.length == 32)
def basePoint = BasePoint(Crypto.publicKeyFromPrivateKey(data :+ 1.toByte))
def add(scalar: Scalar): Scalar = {
val buffer = new BigInteger(1, data).add(new BigInteger(1, scalar.data)).mod(Crypto.curve.getN).toByteArray
val buffer1 = fixSize(buffer.dropWhile(_ == 0))
Scalar(buffer1)
}
def multiply(scalar: Scalar): Scalar = {
val buffer = new BigInteger(1, data).multiply(new BigInteger(1, scalar.data)).mod(Crypto.curve.getN).toByteArray
val buffer1 = fixSize(buffer.dropWhile(_ == 0))
Scalar(buffer1)
}
}
case class BasePoint(data: BinaryData) {
require(data.length == 33)
def add(point: BasePoint): BasePoint = {
val local = Crypto.curve.getCurve.decodePoint(data)
val rhs = Crypto.curve.getCurve.decodePoint(point.data)
BasePoint(local.add(rhs).getEncoded(true))
}
def multiply(scalar: Scalar): BasePoint = {
val local = Crypto.curve.getCurve.decodePoint(data)
val point = local.multiply(new BigInteger(1, scalar.data))
BasePoint(point.getEncoded(true))
}
}
def revocationPubKey(revocationBasePoint: BasePoint, perCommitPoint: BasePoint): BasePoint = {
val a = Scalar(Crypto.sha256(revocationBasePoint.data ++ perCommitPoint.data))
val b = Scalar(Crypto.sha256(perCommitPoint.data ++ revocationBasePoint.data))
revocationBasePoint.multiply(a).add(perCommitPoint.multiply(b))
}
def revocationPrivKey(revocationSecret: Scalar, perCommitSecret: Scalar): Scalar = {
val a = Scalar(Crypto.sha256(revocationSecret.basePoint.data ++ perCommitSecret.basePoint.data))
val b = Scalar(Crypto.sha256(perCommitSecret.basePoint.data ++ revocationSecret.basePoint.data))
revocationSecret.multiply(a).add(perCommitSecret.multiply(b))
}
}

View file

@ -6,6 +6,7 @@ import fr.acinq.bitcoin._
import fr.acinq.eclair.blockchain.ExtendedBitcoinClient
import fr.acinq.eclair.blockchain.rpc.BitcoinJsonRPCClient
import fr.acinq.eclair.channel.Scripts
import fr.acinq.protos.Bolt3.Scalar
import org.junit.runner.RunWith
import org.scalatest.FunSuite
import org.scalatest.junit.JUnitRunner
@ -309,4 +310,25 @@ class Bolt3Spec extends FunSuite {
Transaction.correctlySpends(penaltyTx, htlcSuccessTx :: Nil, ScriptFlags.STANDARD_SCRIPT_VERIFY_FLAGS)
println(s"penalty for out htlc success tx: ${hex(penaltyTx)}")
}
test("derive revocation key") {
object Local {
val revocationSecret = Scalar(Crypto.sha256("local foo".getBytes()))
val revocationBasePoint = revocationSecret.basePoint
val perCommitSecret = Scalar(Crypto.sha256("local bar".getBytes()))
}
object Remote {
val revocationSecret = Scalar(Crypto.sha256("remote foo".getBytes()))
val perCommitSecret = Scalar(Crypto.sha256("remote bar".getBytes()))
val perCommitBasePoint = perCommitSecret.basePoint
}
// I can compute their revocation pubkey
val theirRevocationPubKey = Bolt3.revocationPubKey(Local.revocationBasePoint, Remote.perCommitBasePoint)
// and if they give me their per-commit secret I can compute their revocation privkey
val theirRevocationPrivKey = Bolt3.revocationPrivKey(Local.revocationSecret, Remote.perCommitSecret)
assert(theirRevocationPrivKey.basePoint == theirRevocationPubKey)
}
}