mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-03-19 13:35:17 +01:00
Added secp256k1_schnorrsig_sign to JNI
Added secp256k1_schnorrsig_verify to the JNI Added new schnorrSignWithNonce Fixed schnorr signing and added a test making sure schnorrSign and schnorrSignWithNonce agree Fixed binding, doesn't work yet Added tests, they fail Added BIP 340 test vectors Implemented sigpoint computation using group operators. I believe the nonce is being incorrectly parsed half the time as it should not be treated as an xonly_pubkey Added tests Added Bouncy Castle implementation and further integration Implemented bouncy castle fallback for all secp schnorr functions Implemented FieldElement to abstract modular BigInt computations in the Secp256k1 field Implemented sig in SchnorrDigitalSignature as a FieldElement Vamped up testing Added windows binaries Added osx binaries added windows binaries Responded to review Cleaned up secp commits Responded to review Replaced custom modInverse implementation in FieldElement with java.math.BigInteger.modInverse Cleaned up a couple things for coverage purposes Set bitcoin-s-schnorr to secp branch
This commit is contained in:
parent
5b2ad821ad
commit
85dbf2fd80
21 changed files with 255 additions and 24 deletions
|
@ -147,11 +147,11 @@ stages:
|
||||||
- name: test
|
- name: test
|
||||||
if:
|
if:
|
||||||
commit_message !~ /(?i)^docs:/ AND NOT
|
commit_message !~ /(?i)^docs:/ AND NOT
|
||||||
((branch = master AND type = push) OR (tag IS present))
|
((branch = schnorr-dlc AND type = push) OR (tag IS present))
|
||||||
# don't run tests on merge builds, just publish library
|
# don't run tests on merge builds, just publish library
|
||||||
# and website
|
# and website
|
||||||
- name: release
|
- name: release
|
||||||
if: ((branch = master AND type = push) OR (tag IS present)) AND NOT fork
|
if: ((branch = schnorr-dlc AND type = push) OR (tag IS present)) AND NOT fork
|
||||||
|
|
||||||
script:
|
script:
|
||||||
# Modify PATH to include binaries we are about to download
|
# Modify PATH to include binaries we are about to download
|
||||||
|
|
|
@ -119,7 +119,6 @@ class BouncyCastleSecp256k1Test extends BitcoinSUnitTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
it must "compute schnorr signatures the same" in {
|
it must "compute schnorr signatures the same" in {
|
||||||
forAll(CryptoGenerators.privateKey,
|
forAll(CryptoGenerators.privateKey,
|
||||||
NumberGenerator.bytevector(32),
|
NumberGenerator.bytevector(32),
|
||||||
|
@ -179,5 +178,4 @@ class BouncyCastleSecp256k1Test extends BitcoinSUnitTest {
|
||||||
assert(bouncyCastleSigPoint == secpSigPoint)
|
assert(bouncyCastleSigPoint == secpSigPoint)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,18 +113,34 @@ sealed abstract class ECPrivateKey
|
||||||
}
|
}
|
||||||
|
|
||||||
def schnorrSign(dataToSign: ByteVector): SchnorrDigitalSignature = {
|
def schnorrSign(dataToSign: ByteVector): SchnorrDigitalSignature = {
|
||||||
val auxRand = ECPrivateKey.freshPrivateKey.bytes
|
schnorrSign(dataToSign, CryptoContext.default)
|
||||||
schnorrSign(dataToSign, auxRand)
|
}
|
||||||
|
|
||||||
|
def schnorrSign(
|
||||||
|
dataToSign: ByteVector,
|
||||||
|
context: CryptoContext): SchnorrDigitalSignature = {
|
||||||
|
val auxRand = ECPrivateKey.freshPrivateKey.bytes
|
||||||
|
schnorrSign(dataToSign, auxRand, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: match on CryptoContext once secp version is added
|
|
||||||
def schnorrSign(
|
def schnorrSign(
|
||||||
dataToSign: ByteVector,
|
dataToSign: ByteVector,
|
||||||
auxRand: ByteVector): SchnorrDigitalSignature = {
|
auxRand: ByteVector): SchnorrDigitalSignature = {
|
||||||
schnorrSignWithBouncyCastle(dataToSign, auxRand)
|
schnorrSign(dataToSign, auxRand, CryptoContext.default)
|
||||||
|
}
|
||||||
|
|
||||||
|
def schnorrSign(
|
||||||
|
dataToSign: ByteVector,
|
||||||
|
auxRand: ByteVector,
|
||||||
|
context: CryptoContext): SchnorrDigitalSignature = {
|
||||||
|
context match {
|
||||||
|
case CryptoContext.LibSecp256k1 =>
|
||||||
|
schnorrSignWithSecp(dataToSign, auxRand)
|
||||||
|
case CryptoContext.BouncyCastle =>
|
||||||
|
schnorrSignWithBouncyCastle(dataToSign, auxRand)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
def schnorrSignWithSecp(
|
def schnorrSignWithSecp(
|
||||||
dataToSign: ByteVector,
|
dataToSign: ByteVector,
|
||||||
auxRand: ByteVector): SchnorrDigitalSignature = {
|
auxRand: ByteVector): SchnorrDigitalSignature = {
|
||||||
|
@ -134,7 +150,6 @@ sealed abstract class ECPrivateKey
|
||||||
auxRand.toArray)
|
auxRand.toArray)
|
||||||
SchnorrDigitalSignature(ByteVector(sigBytes))
|
SchnorrDigitalSignature(ByteVector(sigBytes))
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
def schnorrSignWithBouncyCastle(
|
def schnorrSignWithBouncyCastle(
|
||||||
dataToSign: ByteVector,
|
dataToSign: ByteVector,
|
||||||
|
@ -142,14 +157,24 @@ sealed abstract class ECPrivateKey
|
||||||
BouncyCastleUtil.schnorrSign(dataToSign, this, auxRand)
|
BouncyCastleUtil.schnorrSign(dataToSign, this, auxRand)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: match on CryptoContext once secp version is added
|
|
||||||
def schnorrSignWithNonce(
|
def schnorrSignWithNonce(
|
||||||
dataToSign: ByteVector,
|
dataToSign: ByteVector,
|
||||||
nonce: ECPrivateKey): SchnorrDigitalSignature = {
|
nonce: ECPrivateKey): SchnorrDigitalSignature = {
|
||||||
schnorrSignWithNonceWithBouncyCastle(dataToSign, nonce)
|
schnorrSignWithNonce(dataToSign, nonce, CryptoContext.default)
|
||||||
|
}
|
||||||
|
|
||||||
|
def schnorrSignWithNonce(
|
||||||
|
dataToSign: ByteVector,
|
||||||
|
nonce: ECPrivateKey,
|
||||||
|
context: CryptoContext): SchnorrDigitalSignature = {
|
||||||
|
context match {
|
||||||
|
case CryptoContext.LibSecp256k1 =>
|
||||||
|
schnorrSignWithNonceWithSecp(dataToSign, nonce)
|
||||||
|
case CryptoContext.BouncyCastle =>
|
||||||
|
schnorrSignWithNonceWithBouncyCastle(dataToSign, nonce)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
def schnorrSignWithNonceWithSecp(
|
def schnorrSignWithNonceWithSecp(
|
||||||
dataToSign: ByteVector,
|
dataToSign: ByteVector,
|
||||||
nonce: ECPrivateKey): SchnorrDigitalSignature = {
|
nonce: ECPrivateKey): SchnorrDigitalSignature = {
|
||||||
|
@ -159,7 +184,6 @@ sealed abstract class ECPrivateKey
|
||||||
nonce.bytes.toArray)
|
nonce.bytes.toArray)
|
||||||
SchnorrDigitalSignature(ByteVector(sigBytes))
|
SchnorrDigitalSignature(ByteVector(sigBytes))
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
def schnorrSignWithNonceWithBouncyCastle(
|
def schnorrSignWithNonceWithBouncyCastle(
|
||||||
dataToSign: ByteVector,
|
dataToSign: ByteVector,
|
||||||
|
|
|
@ -12,12 +12,20 @@ case class SchnorrPublicKey(bytes: ByteVector) extends NetworkElement {
|
||||||
require(Try(publicKey).isSuccess,
|
require(Try(publicKey).isSuccess,
|
||||||
s"Schnorr public key must be a valid x coordinate, got $bytes")
|
s"Schnorr public key must be a valid x coordinate, got $bytes")
|
||||||
|
|
||||||
// TODO: match on CryptoContext once secp version is added
|
|
||||||
def verify(data: ByteVector, signature: SchnorrDigitalSignature): Boolean = {
|
def verify(data: ByteVector, signature: SchnorrDigitalSignature): Boolean = {
|
||||||
verifyWithBouncyCastle(data, signature)
|
verify(data, signature, CryptoContext.default)
|
||||||
|
}
|
||||||
|
|
||||||
|
def verify(
|
||||||
|
data: ByteVector,
|
||||||
|
signature: SchnorrDigitalSignature,
|
||||||
|
context: CryptoContext): Boolean = {
|
||||||
|
context match {
|
||||||
|
case CryptoContext.LibSecp256k1 => verifyWithSecp(data, signature)
|
||||||
|
case CryptoContext.BouncyCastle => verifyWithBouncyCastle(data, signature)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
def verifyWithSecp(
|
def verifyWithSecp(
|
||||||
data: ByteVector,
|
data: ByteVector,
|
||||||
signature: SchnorrDigitalSignature): Boolean = {
|
signature: SchnorrDigitalSignature): Boolean = {
|
||||||
|
@ -25,7 +33,6 @@ case class SchnorrPublicKey(bytes: ByteVector) extends NetworkElement {
|
||||||
data.toArray,
|
data.toArray,
|
||||||
bytes.toArray)
|
bytes.toArray)
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
def verifyWithBouncyCastle(
|
def verifyWithBouncyCastle(
|
||||||
data: ByteVector,
|
data: ByteVector,
|
||||||
|
@ -34,18 +41,29 @@ case class SchnorrPublicKey(bytes: ByteVector) extends NetworkElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
def computeSigPoint(data: ByteVector, nonce: SchnorrNonce): ECPublicKey = {
|
def computeSigPoint(data: ByteVector, nonce: SchnorrNonce): ECPublicKey = {
|
||||||
computeSigPoint(data, nonce, compressed = true)
|
computeSigPoint(data, nonce, compressed = true, CryptoContext.default)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: match on CryptoContext once secp version is added
|
|
||||||
def computeSigPoint(
|
def computeSigPoint(
|
||||||
data: ByteVector,
|
data: ByteVector,
|
||||||
nonce: SchnorrNonce,
|
nonce: SchnorrNonce,
|
||||||
compressed: Boolean): ECPublicKey = {
|
compressed: Boolean): ECPublicKey = {
|
||||||
computeSigPointWithBouncyCastle(data, nonce, compressed)
|
computeSigPoint(data, nonce, compressed, CryptoContext.default)
|
||||||
|
}
|
||||||
|
|
||||||
|
def computeSigPoint(
|
||||||
|
data: ByteVector,
|
||||||
|
nonce: SchnorrNonce,
|
||||||
|
compressed: Boolean,
|
||||||
|
context: CryptoContext): ECPublicKey = {
|
||||||
|
context match {
|
||||||
|
case CryptoContext.LibSecp256k1 =>
|
||||||
|
computeSigPointWithSecp(data, nonce, compressed)
|
||||||
|
case CryptoContext.BouncyCastle =>
|
||||||
|
computeSigPointWithBouncyCastle(data, nonce, compressed)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
def computeSigPointWithSecp(
|
def computeSigPointWithSecp(
|
||||||
data: ByteVector,
|
data: ByteVector,
|
||||||
nonce: SchnorrNonce,
|
nonce: SchnorrNonce,
|
||||||
|
@ -57,7 +75,6 @@ case class SchnorrPublicKey(bytes: ByteVector) extends NetworkElement {
|
||||||
compressed)
|
compressed)
|
||||||
ECPublicKey(ByteVector(sigPointBytes))
|
ECPublicKey(ByteVector(sigPointBytes))
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
def computeSigPointWithBouncyCastle(
|
def computeSigPointWithBouncyCastle(
|
||||||
data: ByteVector,
|
data: ByteVector,
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
import scala.util.Properties
|
import scala.util.Properties
|
||||||
|
|
||||||
|
version in ThisBuild ~= { version =>
|
||||||
|
val withoutSuffix = version.dropRight(8)
|
||||||
|
withoutSuffix + "SCHNORR-DLC-SNAPSHOT"
|
||||||
|
}
|
||||||
|
|
||||||
val scala2_12 = "2.12.12"
|
val scala2_12 = "2.12.12"
|
||||||
val scala2_13 = "2.13.2"
|
val scala2_13 = "2.13.2"
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit c9bab11ef05ef0cdc0cb0f0e02d3c8e052799767
|
Subproject commit da8fcb8c00611bf9a450763a8d1c41a28b7f76f4
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -515,6 +515,140 @@ public class NativeSecp256k1 {
|
||||||
return resArr;
|
return resArr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* libsecp256k1 schnorr sign - generates a BIP 340 Schnorr signature
|
||||||
|
*
|
||||||
|
* @param data message to sign
|
||||||
|
* @param secKey key to sign with
|
||||||
|
*/
|
||||||
|
public static byte[] schnorrSign(byte[] data, byte[] secKey, byte[] auxRand) throws AssertFailException {
|
||||||
|
checkArgument(data.length == 32 && secKey.length == 32 && auxRand.length == 32);
|
||||||
|
|
||||||
|
ByteBuffer byteBuff = nativeECDSABuffer.get();
|
||||||
|
if (byteBuff == null || byteBuff.capacity() < 32 + 32 + 32) {
|
||||||
|
byteBuff = ByteBuffer.allocateDirect(32 + 32 + 32);
|
||||||
|
byteBuff.order(ByteOrder.nativeOrder());
|
||||||
|
nativeECDSABuffer.set(byteBuff);
|
||||||
|
}
|
||||||
|
byteBuff.rewind();
|
||||||
|
byteBuff.put(data);
|
||||||
|
byteBuff.put(secKey);
|
||||||
|
byteBuff.put(auxRand);
|
||||||
|
|
||||||
|
byte[][] retByteArray;
|
||||||
|
r.lock();
|
||||||
|
try {
|
||||||
|
retByteArray = secp256k1_schnorrsig_sign(byteBuff, Secp256k1Context.getContext());
|
||||||
|
} finally {
|
||||||
|
r.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] sigArray = retByteArray[0];
|
||||||
|
int retVal = new BigInteger(new byte[] { retByteArray[1][0] }).intValue();
|
||||||
|
|
||||||
|
assertEquals(retVal, 1, "Failed return value check.");
|
||||||
|
|
||||||
|
return sigArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* libsecp256k1 schnorr sign - generates a BIP 340 Schnorr signature
|
||||||
|
*
|
||||||
|
* @param data message to sign
|
||||||
|
* @param secKey key to sign with
|
||||||
|
* @param nonce the nonce (k value) used in signing
|
||||||
|
*/
|
||||||
|
public static byte[] schnorrSignWithNonce(byte[] data, byte[] secKey, byte[] nonce) throws AssertFailException {
|
||||||
|
checkArgument(data.length == 32 && secKey.length == 32 && nonce.length == 32);
|
||||||
|
|
||||||
|
ByteBuffer byteBuff = nativeECDSABuffer.get();
|
||||||
|
if (byteBuff == null || byteBuff.capacity() < 32 + 32 + 32) {
|
||||||
|
byteBuff = ByteBuffer.allocateDirect(32 + 32 + 32);
|
||||||
|
byteBuff.order(ByteOrder.nativeOrder());
|
||||||
|
nativeECDSABuffer.set(byteBuff);
|
||||||
|
}
|
||||||
|
byteBuff.rewind();
|
||||||
|
byteBuff.put(data);
|
||||||
|
byteBuff.put(secKey);
|
||||||
|
byteBuff.put(nonce);
|
||||||
|
|
||||||
|
byte[][] retByteArray;
|
||||||
|
r.lock();
|
||||||
|
try {
|
||||||
|
retByteArray = secp256k1_schnorrsig_sign_with_nonce(byteBuff, Secp256k1Context.getContext());
|
||||||
|
} finally {
|
||||||
|
r.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] sigArray = retByteArray[0];
|
||||||
|
int retVal = new BigInteger(new byte[]{retByteArray[1][0]}).intValue();
|
||||||
|
|
||||||
|
assertEquals(retVal, 1, "Failed return value check.");
|
||||||
|
|
||||||
|
return sigArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] schnorrComputeSigPoint(byte[] data, byte[] nonce, byte[] pubkey, boolean compressed) throws AssertFailException {
|
||||||
|
checkArgument(data.length == 32 && nonce.length == 32 && pubkey.length == 32);
|
||||||
|
|
||||||
|
ByteBuffer byteBuff = nativeECDSABuffer.get();
|
||||||
|
if (byteBuff == null || byteBuff.capacity() < 32 + 32 + 32) {
|
||||||
|
byteBuff = ByteBuffer.allocateDirect(32 + 32 + 32);
|
||||||
|
byteBuff.order(ByteOrder.nativeOrder());
|
||||||
|
nativeECDSABuffer.set(byteBuff);
|
||||||
|
}
|
||||||
|
byteBuff.rewind();
|
||||||
|
byteBuff.put(data);
|
||||||
|
byteBuff.put(nonce);
|
||||||
|
byteBuff.put(pubkey);
|
||||||
|
|
||||||
|
byte[][] retByteArray;
|
||||||
|
r.lock();
|
||||||
|
try {
|
||||||
|
retByteArray = secp256k1_schnorrsig_compute_sigpoint(byteBuff, Secp256k1Context.getContext(), compressed);
|
||||||
|
} finally {
|
||||||
|
r.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] pointArray = retByteArray[0];
|
||||||
|
int outputLen = new BigInteger(new byte[] { retByteArray[1][0] }).intValue() & 0xFF;
|
||||||
|
int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue();
|
||||||
|
|
||||||
|
assertEquals(pointArray.length, outputLen, "Got bad point length.");
|
||||||
|
assertEquals(retVal, 1, "Failed return value check.");
|
||||||
|
|
||||||
|
return pointArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* libsecp256k1 schnorr verify - verifies BIP 340 Schnorr signatures
|
||||||
|
*
|
||||||
|
* @param sig signature to verify
|
||||||
|
* @param data message the signature has signed
|
||||||
|
* @param pubx the key that did the signing
|
||||||
|
*/
|
||||||
|
public static boolean schnorrVerify(byte[] sig, byte[] data, byte[] pubx) throws AssertFailException {
|
||||||
|
checkArgument(sig.length == 64 && data.length == 32 && pubx.length == 32);
|
||||||
|
|
||||||
|
ByteBuffer byteBuffer = nativeECDSABuffer.get();
|
||||||
|
if (byteBuffer == null || byteBuffer.capacity() < 64 + 32 + 32) {
|
||||||
|
byteBuffer = ByteBuffer.allocateDirect(64 + 32 + 32);
|
||||||
|
byteBuffer.order(ByteOrder.nativeOrder());
|
||||||
|
nativeECDSABuffer.set(byteBuffer);
|
||||||
|
}
|
||||||
|
byteBuffer.rewind();
|
||||||
|
byteBuffer.put(sig);
|
||||||
|
byteBuffer.put(data);
|
||||||
|
byteBuffer.put(pubx);
|
||||||
|
|
||||||
|
r.lock();
|
||||||
|
try {
|
||||||
|
return secp256k1_schnorrsig_verify(byteBuffer, Secp256k1Context.getContext()) == 1;
|
||||||
|
} finally {
|
||||||
|
r.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* libsecp256k1 randomize - updates the context randomization
|
* libsecp256k1 randomize - updates the context randomization
|
||||||
*
|
*
|
||||||
|
@ -582,4 +716,11 @@ public class NativeSecp256k1 {
|
||||||
|
|
||||||
private static native byte[][] secp256k1_ecdh(ByteBuffer byteBuff, long context, int inputLen);
|
private static native byte[][] secp256k1_ecdh(ByteBuffer byteBuff, long context, int inputLen);
|
||||||
|
|
||||||
|
private static native byte[][] secp256k1_schnorrsig_sign(ByteBuffer byteBuff, long context);
|
||||||
|
|
||||||
|
private static native byte[][] secp256k1_schnorrsig_sign_with_nonce(ByteBuffer byteBuff, long context);
|
||||||
|
|
||||||
|
private static native byte[][] secp256k1_schnorrsig_compute_sigpoint(ByteBuffer byteBuff, long context, boolean compressed);
|
||||||
|
|
||||||
|
private static native int secp256k1_schnorrsig_verify(ByteBuffer byteBuffer, long context);
|
||||||
}
|
}
|
||||||
|
|
|
@ -258,6 +258,52 @@ public class NativeSecp256k1Test {
|
||||||
assertEquals( ecdhString, "2A2A67007A926E6594AF3EB564FC74005B37A9C8AEF2033C4552051B5C87F043" , "testCreateECDHSecret");
|
assertEquals( ecdhString, "2A2A67007A926E6594AF3EB564FC74005B37A9C8AEF2033C4552051B5C87F043" , "testCreateECDHSecret");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSchnorrSign() throws AssertFailException{
|
||||||
|
byte[] data = toByteArray("E48441762FB75010B2AA31A512B62B4148AA3FB08EB0765D76B252559064A614");
|
||||||
|
byte[] secKey = toByteArray("688C77BC2D5AAFF5491CF309D4753B732135470D05B7B2CD21ADD0744FE97BEF");
|
||||||
|
byte[] auxRand = toByteArray("02CCE08E913F22A36C5648D6405A2C7C50106E7AA2F1649E381C7F09D16B80AB");
|
||||||
|
|
||||||
|
byte[] sigArr = NativeSecp256k1.schnorrSign(data, secKey, auxRand);
|
||||||
|
String sigStr = toHex(sigArr);
|
||||||
|
String expectedSig = "F14D7E54FF58C5D019CE9986BE4A0E8B7D643BD08EF2CDF1099E1A457865B5477C988C51634A8DC955950A58FF5DC8C506DDB796121E6675946312680C26CF33";
|
||||||
|
assertEquals(sigStr, expectedSig, "testSchnorrSign");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSchnorrSignWithNonce() throws AssertFailException{
|
||||||
|
byte[] data = toByteArray("E48441762FB75010B2AA31A512B62B4148AA3FB08EB0765D76B252559064A614");
|
||||||
|
byte[] secKey = toByteArray("688C77BC2D5AAFF5491CF309D4753B732135470D05B7B2CD21ADD0744FE97BEF");
|
||||||
|
byte[] nonce = toByteArray("8C8CA771D3C25EB38DE7401818EEDA281AC5446F5C1396148F8D9D67592440FE");
|
||||||
|
|
||||||
|
byte[] sigArr = NativeSecp256k1.schnorrSignWithNonce(data, secKey, nonce);
|
||||||
|
String sigStr = toHex(sigArr);
|
||||||
|
String expectedSig = "5DA618C1936EC728E5CCFF29207F1680DCF4146370BDCFAB0039951B91E3637A50A2A860B130D009405511C3EAFE943E157A0DF2C2020E3E50DF05ADB175332F";
|
||||||
|
assertEquals(sigStr, expectedSig, "testSchnorrSignWithNonce");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSchnorrComputeSigPoint() throws AssertFailException{
|
||||||
|
byte[] data = toByteArray("E48441762FB75010B2AA31A512B62B4148AA3FB08EB0765D76B252559064A614");
|
||||||
|
byte[] nonce = toByteArray("F14D7E54FF58C5D019CE9986BE4A0E8B7D643BD08EF2CDF1099E1A457865B547");
|
||||||
|
byte[] pubKey = toByteArray("B33CC9EDC096D0A83416964BD3C6247B8FECD256E4EFA7870D2C854BDEB33390");
|
||||||
|
|
||||||
|
byte[] pointArr = NativeSecp256k1.schnorrComputeSigPoint(data, nonce, pubKey, true);
|
||||||
|
String pointStr = toHex(pointArr);
|
||||||
|
String expectedPoint = "020D17280B8D2C2BD3B597B4446419C151DC237353D0FB9EC03D4EB7E8DE7EE0A8";
|
||||||
|
assertEquals(pointStr, expectedPoint, "testSchnorrComputeSigPoint");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSchnorrVerify() throws AssertFailException{
|
||||||
|
byte[] sig = toByteArray("F14D7E54FF58C5D019CE9986BE4A0E8B7D643BD08EF2CDF1099E1A457865B5477C988C51634A8DC955950A58FF5DC8C506DDB796121E6675946312680C26CF33");
|
||||||
|
byte[] data = toByteArray("E48441762FB75010B2AA31A512B62B4148AA3FB08EB0765D76B252559064A614");
|
||||||
|
byte[] pubx = toByteArray("B33CC9EDC096D0A83416964BD3C6247B8FECD256E4EFA7870D2C854BDEB33390");
|
||||||
|
|
||||||
|
boolean result = NativeSecp256k1.schnorrVerify(sig, data, pubx);
|
||||||
|
|
||||||
|
assertEquals(result, true, "testSchnorrVerify");
|
||||||
|
}
|
||||||
|
|
||||||
//https://stackoverflow.com/a/19119453/967713
|
//https://stackoverflow.com/a/19119453/967713
|
||||||
private static byte[] toByteArray(final String hex) {
|
private static byte[] toByteArray(final String hex) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue