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

Commit f86dc07

Browse files
authored
Merge pull request #247 from ethereumjs/enforce-buffer-hash-sig
Make hash methods type strict
2 parents 3141eda + dbda438 commit f86dc07

File tree

6 files changed

+282
-30
lines changed

6 files changed

+282
-30
lines changed

src/account.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import * as assert from 'assert'
33
import * as secp256k1 from 'secp256k1'
44
import * as BN from 'bn.js'
55
import { zeros, bufferToHex, toBuffer } from './bytes'
6-
import { keccak, keccak256, rlphash } from './hash'
6+
import { keccak, keccak256, keccakFromString, rlphash } from './hash'
77
import { assertIsHexString, assertIsBuffer } from './helpers'
88

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

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

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

5454
for (let i = 0; i < address.length; i++) {

src/hash.ts

Lines changed: 100 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,52 +3,133 @@ const createHash = require('create-hash')
33
const ethjsUtil = require('ethjs-util')
44
import * as rlp from 'rlp'
55
import { toBuffer, setLengthLeft } from './bytes'
6+
import { assertIsString, assertIsBuffer, assertIsArray, assertIsHexString } from './helpers'
67

78
/**
8-
* Creates Keccak hash of the input
9-
* @param a The input data (Buffer|Array|String|Number) If the string is a 0x-prefixed hex value
10-
* it's interpreted as hexadecimal, otherwise as utf8.
11-
* @param bits The Keccak width
9+
* Creates Keccak hash of a Buffer input
10+
* @param a The input data (Buffer)
11+
* @param bits (number = 256) The Keccak width
1212
*/
13-
export const keccak = function(a: any, bits: number = 256): Buffer {
14-
if (typeof a === 'string' && !ethjsUtil.isHexString(a)) {
15-
a = Buffer.from(a, 'utf8')
16-
} else {
17-
a = toBuffer(a)
18-
}
19-
20-
if (!bits) bits = 256
21-
13+
export const keccak = function(a: Buffer, bits: number = 256): Buffer {
14+
assertIsBuffer(a)
2215
return createKeccakHash(`keccak${bits}`)
2316
.update(a)
2417
.digest()
2518
}
2619

2720
/**
2821
* Creates Keccak-256 hash of the input, alias for keccak(a, 256).
29-
* @param a The input data (Buffer|Array|String|Number)
22+
* @param a The input data (Buffer)
3023
*/
31-
export const keccak256 = function(a: any): Buffer {
24+
export const keccak256 = function(a: Buffer): Buffer {
3225
return keccak(a)
3326
}
3427

3528
/**
36-
* Creates SHA256 hash of the input.
37-
* @param a The input data (Buffer|Array|String|Number)
29+
* Creates Keccak hash of a utf-8 string input
30+
* @param a The input data (String)
31+
* @param bits (number = 256) The Keccak width
3832
*/
39-
export const sha256 = function(a: any): Buffer {
33+
export const keccakFromString = function(a: string, bits: number = 256) {
34+
assertIsString(a)
35+
const buf = Buffer.from(a, 'utf8')
36+
return keccak(buf, bits)
37+
}
38+
39+
/**
40+
* Creates Keccak hash of an 0x-prefixed string input
41+
* @param a The input data (String)
42+
* @param bits (number = 256) The Keccak width
43+
*/
44+
export const keccakFromHexString = function(a: string, bits: number = 256) {
45+
assertIsHexString(a)
46+
return keccak(toBuffer(a), bits)
47+
}
48+
49+
/**
50+
* Creates Keccak hash of a number array input
51+
* @param a The input data (number[])
52+
* @param bits (number = 256) The Keccak width
53+
*/
54+
export const keccakFromArray = function(a: number[], bits: number = 256) {
55+
assertIsArray(a)
56+
return keccak(toBuffer(a), bits)
57+
}
58+
59+
/**
60+
* Creates SHA256 hash of a Buffer input.
61+
* @param a The input data (Buffer)
62+
*/
63+
export const sha256 = function(a: Buffer): Buffer {
64+
assertIsBuffer(a)
65+
return _sha256(a)
66+
}
67+
68+
/**
69+
* Creates SHA256 hash of a string input.
70+
* @param a The input data (string)
71+
*/
72+
export const sha256FromString = function(a: string): Buffer {
73+
assertIsString(a)
74+
return _sha256(a)
75+
}
76+
77+
/**
78+
* Creates SHA256 hash of a number[] input.
79+
* @param a The input data (number[])
80+
*/
81+
export const sha256FromArray = function(a: number[]): Buffer {
82+
assertIsArray(a)
83+
return _sha256(a)
84+
}
85+
86+
/**
87+
* Creates SHA256 hash of an input.
88+
* @param a The input data (Buffer|Array|String)
89+
*/
90+
const _sha256 = function(a: any): Buffer {
4091
a = toBuffer(a)
4192
return createHash('sha256')
4293
.update(a)
4394
.digest()
4495
}
4596

97+
/**
98+
* Creates RIPEMD160 hash of a Buffer input.
99+
* @param a The input data (Buffer)
100+
* @param padded Whether it should be padded to 256 bits or not
101+
*/
102+
export const ripemd160 = function(a: Buffer, padded: boolean): Buffer {
103+
assertIsBuffer(a)
104+
return _ripemd160(a, padded)
105+
}
106+
107+
/**
108+
* Creates RIPEMD160 hash of a string input.
109+
* @param a The input data (String)
110+
* @param padded Whether it should be padded to 256 bits or not
111+
*/
112+
export const ripemd160FromString = function(a: string, padded: boolean): Buffer {
113+
assertIsString(a)
114+
return _ripemd160(a, padded)
115+
}
116+
117+
/**
118+
* Creates RIPEMD160 hash of a number[] input.
119+
* @param a The input data (number[])
120+
* @param padded Whether it should be padded to 256 bits or not
121+
*/
122+
export const ripemd160FromArray = function(a: number[], padded: boolean): Buffer {
123+
assertIsArray(a)
124+
return _ripemd160(a, padded)
125+
}
126+
46127
/**
47128
* Creates RIPEMD160 hash of the input.
48129
* @param a The input data (Buffer|Array|String|Number)
49130
* @param padded Whether it should be padded to 256 bits or not
50131
*/
51-
export const ripemd160 = function(a: any, padded: boolean): Buffer {
132+
const _ripemd160 = function(a: any, padded: boolean): Buffer {
52133
a = toBuffer(a)
53134
const hash = createHash('rmd160')
54135
.update(a)

src/helpers.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,14 @@ export const assertIsArray = function(input: number[]): void {
3232
throw new Error(msg)
3333
}
3434
}
35+
36+
/**
37+
* Throws if input is not a string
38+
* @param {string} input value to check
39+
*/
40+
export const assertIsString = function(input: string): void {
41+
const msg = `This method only supports strings but input was: ${input}`
42+
if (typeof input !== 'string') {
43+
throw new Error(msg)
44+
}
45+
}

src/signature.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as secp256k1 from 'secp256k1'
22
import * as BN from 'bn.js'
33
import { toBuffer, setLengthLeft, bufferToHex } from './bytes'
44
import { keccak } from './hash'
5+
import { assertIsBuffer } from './helpers'
56

67
export interface ECDSASignature {
78
v: number
@@ -134,6 +135,7 @@ export const isValidSignature = function(
134135
* used to produce the signature.
135136
*/
136137
export const hashPersonalMessage = function(message: Buffer): Buffer {
138+
assertIsBuffer(message)
137139
const prefix = Buffer.from(
138140
`\u0019Ethereum Signed Message:\n${message.length.toString()}`,
139141
'utf-8',

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy