import * as Debug from "debug" ; const debug = Debug ( "blockchain:signature" ) ; import * as crypto from "crypto" ; import ConfigInterface from "./../interfaces/ConfigInterface" ; import TransactionInterface from "../interfaces/TransactionInterface" ; import { PUBLIC_SOF } from "./Address" ; import { PUBLIC_EOF } from "./Address" ; import { PRIVATE_SOF } from "./Address" ; import { PRIVATE_EOF } from "./Address" ; const SHA256 = "sha256" ; const HEX = "hex" ; export default class Signature { private config : ConfigInterface ; constructor ( config ) { this . config = config ; } private transactionToString ( transaction ) { return `${ transaction . sender }:${ transaction . recipient }:${ transaction . amount }:` + `${ transaction . payload || "" }:${ transaction . timestamp || "" }` ; } public createSignature ( content , privateKey ) { const signer = crypto . createSign ( SHA256 ) ; signer . update ( content ) ; signer . end ( ) ; const key = `${ PRIVATE_SOF }${ privateKey }${ PRIVATE_EOF }` ; const signature = signer . sign ( key ) ; const signatureAsHex = signature . toString ( HEX ) ; return signatureAsHex ; } public verifySignature ( content , signatureAsHex , publicKey ) { const signature = Buffer . from ( signatureAsHex , HEX ) ; const verifier = crypto . createVerify ( SHA256 ) ; verifier . update ( content ) ; verifier . end ( ) ; const key = `${ PUBLIC_SOF }${ publicKey }${ PUBLIC_EOF }` ; const verified = verifier . verify ( key , signature ) ; if ( verified ) { debug ( "signature is valid" ) ; } else { debug ( "signature is invalid." ) ; } return verified ; } public createTransactionSignature ( transaction , privateKey ) { return this . createSignature ( this . transactionToString ( transaction ) , privateKey ) ; } public verifyTransactionSignature ( transaction ) { if ( ! transaction || typeof transaction . signature === "undefined" ) { return false ; } if ( transaction . sender === this . config . blockchain . mintAddress && ! transaction . signature ) { return true ; } return this . verifySignature ( this . transactionToString ( transaction ) , transaction . signature , transaction . sender ) ; } }