Browse Source

Adding encoders i decoders for signatures and points

pull/3/head
Jør∂¡ 3 years ago
parent
commit
8945a3b929
2 changed files with 68 additions and 14 deletions
  1. +40
    -9
      src/index.ts
  2. +28
    -5
      test/index.test.ts

+ 40
- 9
src/index.ts

@ -16,7 +16,7 @@ export type UnblindedSignature = { s: BigInteger, f: Point }
* Imports a Point from hex string where X and Y coordinates were encoded as 32 * Imports a Point from hex string where X and Y coordinates were encoded as 32
* & 32 bytes in LittleEndian. * & 32 bytes in LittleEndian.
*/ */
export function importPointFromHex(pointHex: string) {
export function pointFromHex(pointHex: string) {
const xBuff = Buffer.from(pointHex.substr(0, 64), 'hex').reverse().toString('hex') const xBuff = Buffer.from(pointHex.substr(0, 64), 'hex').reverse().toString('hex')
const yBuff = Buffer.from(pointHex.substr(64), 'hex').reverse().toString('hex') const yBuff = Buffer.from(pointHex.substr(64), 'hex').reverse().toString('hex')
const x = BigInteger.fromHex(xBuff) const x = BigInteger.fromHex(xBuff)
@ -25,20 +25,41 @@ export function importPointFromHex(pointHex: string) {
return p return p
} }
export function pointToHex(point: Point): string {
const buffX = point.affineX.toBuffer(32).reverse()
const buffY = point.affineY.toBuffer(32).reverse()
return buffX.toString("hex") + buffY.toString("hex")
}
export function signatureFromHex(hexSignature: string): UnblindedSignature {
if (!hexSignature || hexSignature.length != 192) throw new Error("Invalid hex signature (96 bytes expected)")
const s = BigInteger.fromBuffer(Buffer.from(hexSignature.substr(0, 64), "hex").reverse())
const f = pointFromHex(hexSignature.substr(64))
return { s, f }
}
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 flippedHexS = s.toBuffer(32).reverse().toString("hex")
return flippedHexS + pointToHex(f)
}
export function messageToBigNumber(message: string) {
const msg = Buffer.from(message, 'utf8')
return BigInteger.fromBuffer(msg)
}
export function newBigFromString(s: string) { export function newBigFromString(s: string) {
let a = new BigInteger(null, null, null) let a = new BigInteger(null, null, null)
a.fromString(s, null) a.fromString(s, null)
return a return a
} }
function random(bytes: number) {
let k: BigInteger
do {
k = BigInteger.fromByteArrayUnsigned(randomBytes(bytes)) as unknown as BigInteger
} 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.multiply(sk) } return { sk: sk, pk: G.multiply(sk) }
@ -114,3 +135,13 @@ export function verify(m: BigInteger, s: UnblindedSignature, q: Point) {
} }
return false return false
} }
// HELPERS
function random(bytes: number) {
let k: BigInteger
do {
k = BigInteger.fromByteArrayUnsigned(randomBytes(bytes)) as unknown as BigInteger
} while (k.toString() == '0' && k.gcd(n).toString() != '1')
return k
}

+ 28
- 5
test/index.test.ts

@ -1,12 +1,11 @@
import * as assert from 'assert' import * as assert from 'assert'
import * as BigInteger from 'bigi' import * as BigInteger from 'bigi'
import { Point } from 'ecurve'
import { keccak256 } from '@ethersproject/keccak256' import { keccak256 } from '@ethersproject/keccak256'
import { newBigFromString, ecparams, importPointFromHex, newKeyPair, newRequestParameters, blind, blindSign, unblind, verify } from '../src/index'
import { pointFromHex, newKeyPair, newRequestParameters, blind, blindSign, unblind, verify, signatureFromHex, signatureToHex, messageToBigNumber, pointToHex } from '../src/index'
describe('keccak256', function () { describe('keccak256', function () {
it('keccak256', async () => {
it('should hash strings and big numbers', async () => {
const m = BigInteger.fromBuffer(Buffer.from('test', 'utf8')) const m = BigInteger.fromBuffer(Buffer.from('test', 'utf8'))
const mHex = m.toString(16) const mHex = m.toString(16)
const hHex = keccak256('0x' + mHex) const hHex = keccak256('0x' + mHex)
@ -39,12 +38,36 @@ describe('test blind', function () {
}) })
describe('import point from hex', function () { describe('import point from hex', function () {
it('', async () => {
it('should import a point', async () => {
// pointHex and expected values was generated from // pointHex and expected values was generated from
// go-blindsecp256k1 (Point.Bytes()) // go-blindsecp256k1 (Point.Bytes())
const pointHex = '73a68e845e626a2d7f683dd2ceb57956f755d623c0b729af30a72c7bf4dee7a6932d08955c98cf21edf35f5df218b56c41014db06f513cecc85dc3d8671f9521' const pointHex = '73a68e845e626a2d7f683dd2ceb57956f755d623c0b729af30a72c7bf4dee7a6932d08955c98cf21edf35f5df218b56c41014db06f513cecc85dc3d8671f9521'
const p = importPointFromHex(pointHex)
const p = pointFromHex(pointHex)
assert.strictEqual('75493613315673782629634797792529672610524641864826422940379513836118869976691', p.x.toString()) assert.strictEqual('75493613315673782629634797792529672610524641864826422940379513836118869976691', p.x.toString())
assert.strictEqual('15189800969738851359449622716277258420468338317311652509571160848111971610003', p.y.toString()) assert.strictEqual('15189800969738851359449622716277258420468338317311652509571160848111971610003', p.y.toString())
assert.strictEqual(pointToHex(pointFromHex(pointHex)), pointHex)
})
it("should import a signature", () => {
const originalSignatureHex = "36cbb281c7d3f51fa6c027c39d1ec1115e72f4cf78beda1292ef16736894f327a77b4a7e7ba7b7daa54de6a111cb69b6a89bd8c15756a3d0bc620e77b134a9be2cf4d4758c2a5c59381f30bca694b585d9bbb192d349f7220b4e414503cd7eb6"
const { s, f } = signatureFromHex(originalSignatureHex)
assert.strictEqual(s.toString(10), "18070569205902663717816547129479407690196063715098828904678654635357913664310")
assert.strictEqual(f.affineX.toString(10), "86238402060026834577259540812071998074585426519937266202081591629132264536999")
assert.strictEqual(f.affineY.toString(10), "82544976118490904161760686015396902971720732626625394239692986344240783356972")
assert.strictEqual(signatureToHex(signatureFromHex(originalSignatureHex)), originalSignatureHex)
})
it("should import a signature with leading 0's on the big integers", () => {
const originalSignatureHex = "089a89f07bd41560454b1640fd30e51ee088d1be8355275a88e38a38f2e7a3000080fcc14af9c47c8066c6726e7d3cac9370494d5c67936b2978d6cecf5a4d00003ef00b060c47ba874c0764d662eff2d0e9daa8ba766f4aa6a2be8ec3d37500"
const { s, f } = signatureFromHex(originalSignatureHex)
assert.strictEqual(s.toString(10), "289596905226702587911033129111285060518391679824489553383063470810094737928")
assert.strictEqual(f.affineX.toString(10), "136673983650666514404918584888974483560635967304551499498329425981927620608")
assert.strictEqual(f.affineY.toString(10), "208182647280612121090241159906896377333338287898138605151276081386137599488")
assert.strictEqual(signatureToHex(signatureFromHex(originalSignatureHex)), originalSignatureHex)
}) })
}) })

Loading…
Cancel
Save