@bsv/sdk
Version:
BSV Blockchain Software Development Kit
121 lines (99 loc) • 3.71 kB
text/typescript
import * as ECDSA from '../../primitives/ECDSA'
import BigNumber from '../../primitives/BigNumber'
import Curve from '../../primitives/Curve'
import Signature from '../../primitives/Signature'
import Point from '../../primitives/Point'
const msg = new BigNumber('deadbeef', 16)
const key = new BigNumber(
'1e5edd45de6d22deebef4596b80444ffcc29143839c1dce18db470e25b4be7b5',
16
)
const curve = new Curve()
const pub = curve.g.mul(key)
const wrongPub = curve.g.mul(new BigNumber(33))
describe('ECDSA', () => {
it('should sign and verify', () => {
const signature = ECDSA.sign(msg, key)
expect(ECDSA.verify(msg, signature, pub)).toBeTruthy()
})
it('should encode and decode with DER', () => {
const signature = ECDSA.sign(msg, key)
const encoded = signature.toDER()
expect(encoded.length).toBe(71)
const decoded = Signature.fromDER(encoded)
expect(decoded.r.toString(16)).toEqual(signature.r.toString(16))
expect(decoded.s.toString(16)).toEqual(signature.s.toString(16))
})
it('should encode and decode with hex DER', () => {
const signature = ECDSA.sign(msg, key)
const encoded = signature.toDER('hex')
expect(encoded.length).toBe(142)
const decoded = Signature.fromDER(encoded, 'hex')
expect(decoded.r.toString(16)).toEqual(signature.r.toString(16))
expect(decoded.s.toString(16)).toEqual(signature.s.toString(16))
})
it('should have `signature.s <= keys.ec.nh`', () => {
// key.sign(msg, options)
const sign = ECDSA.sign(msg, key, true)
expect(sign.s.cmp(curve.n.ushrn(1)) <= 0).toBeTruthy()
})
it('should support `options.k`', () => {
const sign = ECDSA.sign(msg, key, undefined, new BigNumber(1358))
expect(ECDSA.verify(msg, sign, pub)).toBeTruthy()
})
it('should not verify an incorrectly signed message', () => {
const wrongMessage = new BigNumber(
'BA5AABBE1AA9B6EC1E2ADB2DF99699344345678901234567890ABCDEFABCDEF02',
16
)
const signature = ECDSA.sign(msg, key)
const result = ECDSA.verify(wrongMessage, signature, pub)
expect(result).toBe(false)
})
it('should not verify signature with wrong public key', () => {
const signature = ECDSA.sign(msg, key)
expect(ECDSA.verify(msg, signature, wrongPub)).toBeFalsy()
})
it('should accept custom k = 1 and k = n-1', () => {
const n = curve.n
const one = new BigNumber(1)
// k = 1 → valid
const k1 = one
const sig1 = ECDSA.sign(msg, key, undefined, k1)
expect(ECDSA.verify(msg, sig1, pub)).toBeTruthy()
// k = n-1 → valid
const km1 = n.subn(1)
const sig2 = ECDSA.sign(msg, key, undefined, km1)
expect(ECDSA.verify(msg, sig2, pub)).toBeTruthy()
})
it('should reject custom k < 1 or k > n-1', () => {
const n = curve.n
// k = 0 → invalid
expect(() =>
ECDSA.sign(msg, key, undefined, new BigNumber(0))
).toThrow()
// k = n → invalid
expect(() =>
ECDSA.sign(msg, key, undefined, n)
).toThrow()
})
it('k·G + (−k·G) results in point at infinity (TOB-25)', () => {
const k = new BigNumber('123456789abcdef', 16)
const P = curve.g.mul(k)
const negP = P.neg()
const sum = P.add(negP)
expect(sum.isInfinity()).toBe(true)
})
it('scalar multiplication by zero returns point at infinity (TOB-25)', () => {
const zero = new BigNumber(0)
const result = curve.g.mul(zero)
expect(result.isInfinity()).toBe(true)
})
it('ECDSA verify rejects point-at-infinity public key (TOB-25)', () => {
const signature = ECDSA.sign(msg, key)
const infinityPub = new Point(null, null)
expect(() =>
ECDSA.verify(msg, signature, infinityPub)
).toThrow()
})
})