@cloud-cryptographic-wallet/signer
Advanced tools
Comparing version 0.0.3 to 0.0.4
@@ -1,5 +0,51 @@ | ||
export * from "./address.js"; | ||
export * from "./bytes.js"; | ||
export * from "./public-key.js"; | ||
export * from "./signature.js"; | ||
export * from "./signer.js"; | ||
declare class Bytes { | ||
readonly buffer: ArrayBuffer; | ||
private constructor(); | ||
get asUint8Array(): Uint8Array; | ||
static fromArrayBuffer(buffer: ArrayBuffer): Bytes; | ||
static fromString(hex: string): Bytes; | ||
static concat(bytesList: Bytes[]): Bytes; | ||
slice(begin: number, end?: number | undefined): Bytes; | ||
readUInt8(index: number): number; | ||
equals(other: Bytes): boolean; | ||
toString(): string; | ||
get length(): number; | ||
} | ||
declare class Address { | ||
readonly bytes: Bytes; | ||
private constructor(); | ||
static fromBytes(bytes: Bytes): Address; | ||
equals(other: Address): boolean; | ||
toString(): string; | ||
private toChecksumAddress; | ||
} | ||
declare class PublicKey { | ||
readonly bytes: Bytes; | ||
private constructor(); | ||
static fromBytes(bytes: Bytes): PublicKey; | ||
toAddress(): Address; | ||
equals(other: PublicKey): boolean; | ||
} | ||
declare class Signature { | ||
readonly bytes: Bytes; | ||
private validate; | ||
private constructor(); | ||
recoveryPublicKey(hash: Bytes): PublicKey; | ||
static fromBytes(bytes: Bytes): Signature; | ||
static fromRSV(r: Bytes, s: Bytes, v: number): Signature; | ||
static fromHash(hash: Bytes, publicKey: PublicKey, r: Bytes, s: Bytes): Signature; | ||
get r(): Bytes; | ||
get s(): Bytes; | ||
get v(): number; | ||
get recovery(): number; | ||
} | ||
interface Signer { | ||
sign(hash: Bytes): Promise<Signature>; | ||
getPublicKey(): Promise<PublicKey>; | ||
} | ||
export { Address, Bytes, PublicKey, Signature, Signer }; |
@@ -1,6 +0,179 @@ | ||
export * from "./address.js"; | ||
export * from "./bytes.js"; | ||
export * from "./public-key.js"; | ||
export * from "./signature.js"; | ||
export * from "./signer.js"; | ||
// src/address.ts | ||
import createKeccakHash from "keccak"; | ||
var Address = class { | ||
constructor(bytes) { | ||
this.bytes = bytes; | ||
if (this.bytes.length !== 20) { | ||
throw TypeError(`Address: invalid public key. address must be 20 bytes. actual: ${this.bytes.length}`); | ||
} | ||
} | ||
static fromBytes(bytes) { | ||
return new Address(bytes); | ||
} | ||
equals(other) { | ||
return this.bytes.equals(other.bytes); | ||
} | ||
toString() { | ||
const withoutPrefix = this.bytes.toString().slice(2); | ||
return `0x${this.toChecksumAddress(withoutPrefix)}`; | ||
} | ||
toChecksumAddress(address) { | ||
const hash = createKeccakHash("keccak256").update(address).digest("hex"); | ||
return address.split("").map((c, i) => { | ||
return Number.parseInt(hash[i], 16) > 7 ? c.toUpperCase() : c; | ||
}).join(""); | ||
} | ||
}; | ||
// src/bytes.ts | ||
var Bytes = class { | ||
constructor(buffer) { | ||
this.buffer = buffer; | ||
} | ||
get asUint8Array() { | ||
return new Uint8Array(this.buffer); | ||
} | ||
static fromArrayBuffer(buffer) { | ||
return new Bytes(buffer); | ||
} | ||
static fromString(hex) { | ||
const withoutPrefix = hex.startsWith("0x") ? hex.slice(2) : hex; | ||
if (!withoutPrefix.match(/[0-9a-f]+/i)) { | ||
throw new Error(`Bytes: string must be hexadecimal. actual: ${withoutPrefix}`); | ||
} | ||
if (withoutPrefix.length % 2 !== 0) { | ||
throw new Error(`Bytes: string must be an even number of length. actual: ${withoutPrefix.length}`); | ||
} | ||
const view = new Uint8Array(withoutPrefix.length / 2); | ||
for (let i = 0; i < withoutPrefix.length; i += 2) { | ||
view[i / 2] = Number.parseInt(withoutPrefix.slice(i, i + 2), 16); | ||
} | ||
return Bytes.fromArrayBuffer(view.buffer); | ||
} | ||
static concat(bytesList) { | ||
const total = bytesList.reduce((prev, cur) => prev + cur.length, 0); | ||
const result = new Uint8Array(total); | ||
let offset = 0; | ||
for (const bytes of bytesList) { | ||
result.set(bytes.asUint8Array, offset); | ||
offset += bytes.length; | ||
} | ||
return Bytes.fromArrayBuffer(result.buffer); | ||
} | ||
slice(begin, end) { | ||
return Bytes.fromArrayBuffer(this.buffer.slice(begin, end)); | ||
} | ||
readUInt8(index) { | ||
const result = this.asUint8Array[index]; | ||
if (result == void 0) { | ||
throw new Error(`Bytes: invalid index access. index: ${index}`); | ||
} | ||
return result; | ||
} | ||
equals(other) { | ||
return this.asUint8Array.every((_, index) => { | ||
return this.readUInt8(index) === other.readUInt8(index); | ||
}); | ||
} | ||
toString() { | ||
const withoutPrefix = Array.from(this.asUint8Array).map((value) => value.toString(16).padStart(2, "0")).join(""); | ||
return `0x${withoutPrefix}`; | ||
} | ||
get length() { | ||
return this.buffer.byteLength; | ||
} | ||
}; | ||
// src/public-key.ts | ||
import createKeccakHash2 from "keccak"; | ||
var PublicKey = class { | ||
constructor(bytes) { | ||
this.bytes = bytes; | ||
if (this.bytes.length !== 64) { | ||
throw TypeError(`PublicKey: invalid public key. buffer length must be 64 bytes. actual: ${this.bytes.length}`); | ||
} | ||
} | ||
static fromBytes(bytes) { | ||
return new PublicKey(bytes); | ||
} | ||
toAddress() { | ||
const address = createKeccakHash2("keccak256").update(Buffer.from(this.bytes.toString().slice(2), "hex")).digest().slice(12, 32); | ||
return Address.fromBytes(Bytes.fromString(address.toString("hex"))); | ||
} | ||
equals(other) { | ||
return this.bytes.equals(other.bytes); | ||
} | ||
}; | ||
// src/signature.ts | ||
import BN from "bn.js"; | ||
import secp256k1 from "secp256k1"; | ||
var Signature = class { | ||
validate() { | ||
if (this.bytes.length !== 65) { | ||
throw TypeError(`Signature: invalid signature. buffer length must be 65 bytes. actual: ${this.bytes.length}`); | ||
} | ||
if (![27, 28].includes(this.v)) { | ||
throw Error(`Signature: invalid signature. V must be 27 or 28. actual: ${this.recovery}`); | ||
} | ||
} | ||
constructor(bytes) { | ||
this.bytes = bytes; | ||
this.validate(); | ||
const secp256k1N = new BN("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", 16); | ||
const secp256k1halfN = secp256k1N.div(new BN(2)); | ||
if (new BN(this.s.asUint8Array).cmp(secp256k1halfN) > 0) { | ||
const reversedS = secp256k1N.sub(new BN(this.s.asUint8Array)).toArrayLike(Uint8Array); | ||
const bytes2 = Bytes.concat([ | ||
this.r, | ||
Bytes.fromArrayBuffer(reversedS.buffer), | ||
Bytes.fromArrayBuffer(new Uint8Array([this.v % 2 + 27]).buffer) | ||
]); | ||
this.bytes = bytes2; | ||
this.validate(); | ||
} | ||
} | ||
recoveryPublicKey(hash) { | ||
const publicKey = secp256k1.ecdsaRecover(Bytes.concat([this.r, this.s]).asUint8Array, this.recovery, hash.asUint8Array, false).slice(1); | ||
return PublicKey.fromBytes(Bytes.fromArrayBuffer(publicKey.buffer)); | ||
} | ||
static fromBytes(bytes) { | ||
return new Signature(bytes); | ||
} | ||
static fromRSV(r, s, v) { | ||
const recovery = new Uint8Array([v]); | ||
const bytes = Bytes.concat([r, s, Bytes.fromArrayBuffer(recovery.buffer)]); | ||
return Signature.fromBytes(bytes); | ||
} | ||
static fromHash(hash, publicKey, r, s) { | ||
const candidate = [27, 28].filter((v) => { | ||
const candidateSignature = Signature.fromRSV(r, s, v); | ||
const candidatePublicKey = candidateSignature.recoveryPublicKey(hash); | ||
return publicKey.equals(candidatePublicKey); | ||
}); | ||
if (candidate.length === 1) { | ||
const v = candidate[0]; | ||
return Signature.fromRSV(r, s, v); | ||
} | ||
throw new Error(`Signature: failed to solve V.`); | ||
} | ||
get r() { | ||
return this.bytes.slice(0, 32); | ||
} | ||
get s() { | ||
return this.bytes.slice(32, 64); | ||
} | ||
get v() { | ||
return this.bytes.readUInt8(64); | ||
} | ||
get recovery() { | ||
return 1 - this.v % 2; | ||
} | ||
}; | ||
export { | ||
Address, | ||
Bytes, | ||
PublicKey, | ||
Signature | ||
}; | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "@cloud-cryptographic-wallet/signer", | ||
"version": "0.0.3", | ||
"version": "0.0.4", | ||
"repository": { | ||
@@ -11,3 +11,8 @@ "type": "git", | ||
"main": "./dist/index.js", | ||
"exports": "./dist/index.js", | ||
"exports": { | ||
"import": "./dist/index.js", | ||
"require": "./dist/index.cjs", | ||
"node": "./dist/index.cjs", | ||
"default": "./dist/index.js" | ||
}, | ||
"types": "./dist/index.d.ts", | ||
@@ -34,9 +39,9 @@ "engines": { | ||
"@types/keccak": "^3.0.1", | ||
"@types/secp256k1": "^4.0.3" | ||
"@types/secp256k1": "^4.0.3", | ||
"tsup": "^5.12.1" | ||
}, | ||
"scripts": { | ||
"prebuild": "rm -rf dist", | ||
"build": "tsc" | ||
"build": "tsup" | ||
}, | ||
"gitHead": "302d5d14fd3294b3218fc2d2137418573b8c022c" | ||
"gitHead": "a4c4787f203e0fec56267b0ca4a1f90df172d168" | ||
} |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
58074
969
4
17