Skip to content
This repository has been archived by the owner on Jun 17, 2021. It is now read-only.

Commit

Permalink
Merge pull request #247 from ethereumjs/enforce-buffer-hash-sig
Browse files Browse the repository at this point in the history
Make hash methods type strict
  • Loading branch information
holgerd77 authored Apr 29, 2020
2 parents 3141eda + dbda438 commit f86dc07
Show file tree
Hide file tree
Showing 6 changed files with 282 additions and 30 deletions.
4 changes: 2 additions & 2 deletions src/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as assert from 'assert'
import * as secp256k1 from 'secp256k1'
import * as BN from 'bn.js'
import { zeros, bufferToHex, toBuffer } from './bytes'
import { keccak, keccak256, rlphash } from './hash'
import { keccak, keccak256, keccakFromString, rlphash } from './hash'
import { assertIsHexString, assertIsBuffer } from './helpers'

/**
Expand Down Expand Up @@ -48,7 +48,7 @@ export const toChecksumAddress = function(hexAddress: string, eip1191ChainId?: n

const prefix = eip1191ChainId !== undefined ? eip1191ChainId.toString() + '0x' : ''

const hash = keccak(prefix + address).toString('hex')
const hash = keccakFromString(prefix + address).toString('hex')
let ret = '0x'

for (let i = 0; i < address.length; i++) {
Expand Down
119 changes: 100 additions & 19 deletions src/hash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,52 +3,133 @@ const createHash = require('create-hash')
const ethjsUtil = require('ethjs-util')
import * as rlp from 'rlp'
import { toBuffer, setLengthLeft } from './bytes'
import { assertIsString, assertIsBuffer, assertIsArray, assertIsHexString } from './helpers'

/**
* Creates Keccak hash of the input
* @param a The input data (Buffer|Array|String|Number) If the string is a 0x-prefixed hex value
* it's interpreted as hexadecimal, otherwise as utf8.
* @param bits The Keccak width
* Creates Keccak hash of a Buffer input
* @param a The input data (Buffer)
* @param bits (number = 256) The Keccak width
*/
export const keccak = function(a: any, bits: number = 256): Buffer {
if (typeof a === 'string' && !ethjsUtil.isHexString(a)) {
a = Buffer.from(a, 'utf8')
} else {
a = toBuffer(a)
}

if (!bits) bits = 256

export const keccak = function(a: Buffer, bits: number = 256): Buffer {
assertIsBuffer(a)
return createKeccakHash(`keccak${bits}`)
.update(a)
.digest()
}

/**
* Creates Keccak-256 hash of the input, alias for keccak(a, 256).
* @param a The input data (Buffer|Array|String|Number)
* @param a The input data (Buffer)
*/
export const keccak256 = function(a: any): Buffer {
export const keccak256 = function(a: Buffer): Buffer {
return keccak(a)
}

/**
* Creates SHA256 hash of the input.
* @param a The input data (Buffer|Array|String|Number)
* Creates Keccak hash of a utf-8 string input
* @param a The input data (String)
* @param bits (number = 256) The Keccak width
*/
export const sha256 = function(a: any): Buffer {
export const keccakFromString = function(a: string, bits: number = 256) {
assertIsString(a)
const buf = Buffer.from(a, 'utf8')
return keccak(buf, bits)
}

/**
* Creates Keccak hash of an 0x-prefixed string input
* @param a The input data (String)
* @param bits (number = 256) The Keccak width
*/
export const keccakFromHexString = function(a: string, bits: number = 256) {
assertIsHexString(a)
return keccak(toBuffer(a), bits)
}

/**
* Creates Keccak hash of a number array input
* @param a The input data (number[])
* @param bits (number = 256) The Keccak width
*/
export const keccakFromArray = function(a: number[], bits: number = 256) {
assertIsArray(a)
return keccak(toBuffer(a), bits)
}

/**
* Creates SHA256 hash of a Buffer input.
* @param a The input data (Buffer)
*/
export const sha256 = function(a: Buffer): Buffer {
assertIsBuffer(a)
return _sha256(a)
}

/**
* Creates SHA256 hash of a string input.
* @param a The input data (string)
*/
export const sha256FromString = function(a: string): Buffer {
assertIsString(a)
return _sha256(a)
}

/**
* Creates SHA256 hash of a number[] input.
* @param a The input data (number[])
*/
export const sha256FromArray = function(a: number[]): Buffer {
assertIsArray(a)
return _sha256(a)
}

/**
* Creates SHA256 hash of an input.
* @param a The input data (Buffer|Array|String)
*/
const _sha256 = function(a: any): Buffer {
a = toBuffer(a)
return createHash('sha256')
.update(a)
.digest()
}

/**
* Creates RIPEMD160 hash of a Buffer input.
* @param a The input data (Buffer)
* @param padded Whether it should be padded to 256 bits or not
*/
export const ripemd160 = function(a: Buffer, padded: boolean): Buffer {
assertIsBuffer(a)
return _ripemd160(a, padded)
}

/**
* Creates RIPEMD160 hash of a string input.
* @param a The input data (String)
* @param padded Whether it should be padded to 256 bits or not
*/
export const ripemd160FromString = function(a: string, padded: boolean): Buffer {
assertIsString(a)
return _ripemd160(a, padded)
}

/**
* Creates RIPEMD160 hash of a number[] input.
* @param a The input data (number[])
* @param padded Whether it should be padded to 256 bits or not
*/
export const ripemd160FromArray = function(a: number[], padded: boolean): Buffer {
assertIsArray(a)
return _ripemd160(a, padded)
}

/**
* Creates RIPEMD160 hash of the input.
* @param a The input data (Buffer|Array|String|Number)
* @param padded Whether it should be padded to 256 bits or not
*/
export const ripemd160 = function(a: any, padded: boolean): Buffer {
const _ripemd160 = function(a: any, padded: boolean): Buffer {
a = toBuffer(a)
const hash = createHash('rmd160')
.update(a)
Expand Down
11 changes: 11 additions & 0 deletions src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,14 @@ export const assertIsArray = function(input: number[]): void {
throw new Error(msg)
}
}

/**
* Throws if input is not a string
* @param {string} input value to check
*/
export const assertIsString = function(input: string): void {
const msg = `This method only supports strings but input was: ${input}`
if (typeof input !== 'string') {
throw new Error(msg)
}
}
2 changes: 2 additions & 0 deletions src/signature.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as secp256k1 from 'secp256k1'
import * as BN from 'bn.js'
import { toBuffer, setLengthLeft, bufferToHex } from './bytes'
import { keccak } from './hash'
import { assertIsBuffer } from './helpers'

export interface ECDSASignature {
v: number
Expand Down Expand Up @@ -134,6 +135,7 @@ export const isValidSignature = function(
* used to produce the signature.
*/
export const hashPersonalMessage = function(message: Buffer): Buffer {
assertIsBuffer(message)
const prefix = Buffer.from(
`\u0019Ethereum Signed Message:\n${message.length.toString()}`,
'utf-8',
Expand Down
Loading

0 comments on commit f86dc07

Please sign in to comment.