mirror of
https://github.com/arnaucube/blindsecp256k1-js.git
synced 2026-02-07 03:16:43 +01:00
Allowing to encode and decode hex signatures (#2)
* Allowing to encode and decode hex signatures * Minor arrangement
This commit is contained in:
45
src/index.ts
45
src/index.ts
@@ -37,14 +37,6 @@ export function decodePoint(hexPoint: string): Point {
|
|||||||
return secp256k1.keyFromPublic(Buffer.from(hexPoint, "hex")).getPublic()
|
return secp256k1.keyFromPublic(Buffer.from(hexPoint, "hex")).getPublic()
|
||||||
}
|
}
|
||||||
|
|
||||||
function random(bytes: number) {
|
|
||||||
let k: BigNumber
|
|
||||||
do {
|
|
||||||
k = new BigNumber(randomBytes(bytes))
|
|
||||||
} while (k.toString() == "0" && k.gcd(n).toString() != "1")
|
|
||||||
return k
|
|
||||||
}
|
|
||||||
|
|
||||||
export function newKeyPair() {
|
export function newKeyPair() {
|
||||||
const sk = random(32)
|
const sk = random(32)
|
||||||
return { sk: sk, pk: G.mul(sk) }
|
return { sk: sk, pk: G.mul(sk) }
|
||||||
@@ -121,3 +113,40 @@ export function verify(m: BigNumber, s: UnblindedSignature, q: Point) {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function signatureToHex(signature: UnblindedSignature): string {
|
||||||
|
if (!signature || !signature.f || !signature.s) throw new Error("The signature is empty")
|
||||||
|
const { f, s } = signature
|
||||||
|
|
||||||
|
// hex(swapEndiannes(s) ) + hex(f)
|
||||||
|
const hexPaddedS = zeroPad(s.toBuffer().toString("hex"), 32)
|
||||||
|
const flippedHexS = Buffer.from(hexPaddedS, "hex").reverse().toString("hex")
|
||||||
|
|
||||||
|
return zeroPad(flippedHexS, 32) + zeroPad(f.encode("hex", false).substr(2), 64) // strip 04
|
||||||
|
}
|
||||||
|
|
||||||
|
export function signatureFromHex(hexSignature: string): UnblindedSignature {
|
||||||
|
if (!hexSignature || hexSignature.length != 192) throw new Error("Invalid hex signature (96 bytes expected)")
|
||||||
|
|
||||||
|
const s = new BigNumber(Buffer.from(hexSignature.substr(0, 64), "hex").reverse())
|
||||||
|
const f = decodePoint("04" + hexSignature.substr(64))
|
||||||
|
return { s, f }
|
||||||
|
}
|
||||||
|
|
||||||
|
// HELPERS
|
||||||
|
|
||||||
|
function random(bytes: number) {
|
||||||
|
let k: BigNumber
|
||||||
|
do {
|
||||||
|
k = new BigNumber(randomBytes(bytes))
|
||||||
|
} while (k.toString() == "0" && k.gcd(n).toString() != "1")
|
||||||
|
return k
|
||||||
|
}
|
||||||
|
|
||||||
|
function zeroPad(hexString: string, byteLength: number) {
|
||||||
|
if (hexString.length > (byteLength * 2)) throw new Error("Out of bounds")
|
||||||
|
while (hexString.length < (byteLength * 2)) {
|
||||||
|
hexString = "0" + hexString
|
||||||
|
}
|
||||||
|
return hexString
|
||||||
|
}
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ import {
|
|||||||
verify,
|
verify,
|
||||||
hashBigNumber,
|
hashBigNumber,
|
||||||
Point,
|
Point,
|
||||||
BigNumber
|
BigNumber,
|
||||||
|
signatureToHex,
|
||||||
|
signatureFromHex
|
||||||
} from "../src/index"
|
} from "../src/index"
|
||||||
|
|
||||||
describe("keccak256", function () {
|
describe("keccak256", function () {
|
||||||
@@ -53,3 +55,40 @@ describe("blind signatures", function () {
|
|||||||
assert(verified)
|
assert(verified)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe("encoding", () => {
|
||||||
|
it("should encode and decode signatures", () => {
|
||||||
|
const { sk } = newKeyPair()
|
||||||
|
const { k, signerR } = newRequestParameters()
|
||||||
|
const msg = messageToBigNumber("test")
|
||||||
|
const { mBlinded, userSecretData } = blind(msg, signerR)
|
||||||
|
const sBlind = blindSign(sk, mBlinded, k)
|
||||||
|
const sig = unblind(sBlind, userSecretData)
|
||||||
|
|
||||||
|
const hexSignature = signatureToHex(sig)
|
||||||
|
assert.strictEqual(hexSignature.length, 192)
|
||||||
|
|
||||||
|
const decodedSig = signatureFromHex(hexSignature)
|
||||||
|
assert.strictEqual(decodedSig.f.encode("hex", false).length, 130)
|
||||||
|
|
||||||
|
assert.strictEqual(signatureToHex(signatureFromHex(hexSignature)), hexSignature)
|
||||||
|
|
||||||
|
// explicit values
|
||||||
|
const hexSignature2 = "089a89f07bd41560454b1640fd30e51ee088d1be8355275a88e38a38f2e7a3af9e80fcc14af9c47c8066c6726e7d3cac9370494d5c67936b2978d6cecf5a4d21bf3ef00b060c47ba874c0764d662eff2d0e9daa8ba766f4aa6a2be8ec3d37523"
|
||||||
|
|
||||||
|
const decodedSig2 = signatureFromHex(hexSignature2)
|
||||||
|
assert.strictEqual(decodedSig2.s.toString("hex"), "afa3e7f2388ae3885a275583bed188e01ee530fd40164b456015d47bf0899a08")
|
||||||
|
assert.strictEqual(decodedSig2.f.encode("hex", false).substr(2), "9e80fcc14af9c47c8066c6726e7d3cac9370494d5c67936b2978d6cecf5a4d21bf3ef00b060c47ba874c0764d662eff2d0e9daa8ba766f4aa6a2be8ec3d37523")
|
||||||
|
|
||||||
|
assert.strictEqual(signatureToHex(signatureFromHex(hexSignature2)), hexSignature2)
|
||||||
|
|
||||||
|
// swapEndianness(s) starting with 0
|
||||||
|
const hexSignature3 = "089a89f07bd41560454b1640fd30e51ee088d1be8355275a88e38a38f2e7a30f9e80fcc14af9c47c8066c6726e7d3cac9370494d5c67936b2978d6cecf5a4d21bf3ef00b060c47ba874c0764d662eff2d0e9daa8ba766f4aa6a2be8ec3d37523"
|
||||||
|
|
||||||
|
const decodedSig3 = signatureFromHex(hexSignature3)
|
||||||
|
assert.strictEqual(decodedSig3.s.toString("hex"), /* 0 */ "fa3e7f2388ae3885a275583bed188e01ee530fd40164b456015d47bf0899a08")
|
||||||
|
assert.strictEqual(decodedSig3.f.encode("hex", false).substr(2), "9e80fcc14af9c47c8066c6726e7d3cac9370494d5c67936b2978d6cecf5a4d21bf3ef00b060c47ba874c0764d662eff2d0e9daa8ba766f4aa6a2be8ec3d37523")
|
||||||
|
|
||||||
|
assert.strictEqual(signatureToHex(signatureFromHex(hexSignature3)), hexSignature3)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user