Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Bringing back js-sha3 to fix in-browser signing #4063

Merged
merged 5 commits into from
Jan 6, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,6 @@
"blockies": "0.0.2",
"brace": "0.9.0",
"bytes": "2.4.0",
"crypto-js": "3.1.9-1",
"debounce": "1.0.0",
"es6-error": "4.0.0",
"es6-promise": "4.0.5",
Expand Down
18 changes: 12 additions & 6 deletions js/src/api/util/format.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,21 @@ export function bytesToHex (bytes) {
return '0x' + bytes.map((b) => ('0' + b.toString(16)).slice(-2)).join('');
}

export function hex2Ascii (_hex) {
const hex = /^(?:0x)?(.*)$/.exec(_hex.toString())[1];
export function hexToBytes (hex) {
const raw = toHex(hex).slice(2);
const bytes = [];

let str = '';

for (let i = 0; i < hex.length; i += 2) {
str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
for (let i = 0; i < raw.length; i += 2) {
bytes.push(parseInt(raw.substr(i, 2), 16));
}

return bytes;
}

export function hexToAscii (hex) {
const bytes = hexToBytes(hex);
const str = bytes.map((byte) => String.fromCharCode(byte)).join('');

return str;
}

Expand Down
44 changes: 43 additions & 1 deletion js/src/api/util/format.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

import { bytesToHex } from './format';
import { bytesToHex, hexToBytes, hexToAscii, bytesToAscii, asciiToHex } from './format';

describe('api/util/format', () => {
describe('bytesToHex', () => {
Expand All @@ -26,4 +26,46 @@ describe('api/util/format', () => {
expect(bytesToHex([0, 15, 16])).to.equal('0x000f10');
});
});

describe('hexToBytes', () => {
it('correctly converts an empty string', () => {
expect(hexToBytes('')).to.deep.equal([]);
expect(hexToBytes('0x')).to.deep.equal([]);
});

it('correctly converts a non-empty string', () => {
expect(hexToBytes('0x000f10')).to.deep.equal([0, 15, 16]);
});
});

describe('asciiToHex', () => {
it('correctly converts an empty string', () => {
expect(asciiToHex('')).to.equal('0x');
});

it('correctly converts a non-empty string', () => {
expect(asciiToHex('abc')).to.equal('0x616263');
});
});

describe('hexToAscii', () => {
it('correctly converts an empty string', () => {
expect(hexToAscii('')).to.equal('');
expect(hexToAscii('0x')).to.equal('');
});

it('correctly converts a non-empty string', () => {
expect(hexToAscii('0x616263')).to.equal('abc');
});
});

describe('bytesToAscii', () => {
it('correctly converts an empty string', () => {
expect(bytesToAscii([])).to.equal('');
});

it('correctly converts a non-empty string', () => {
expect(bytesToAscii([97, 98, 99])).to.equal('abc');
});
});
});
4 changes: 2 additions & 2 deletions js/src/api/util/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

import { isAddress as isAddressValid, toChecksumAddress } from '../../abi/util/address';
import { decodeCallData, decodeMethodInput, methodToAbi } from './decode';
import { bytesToHex, hex2Ascii, asciiToHex } from './format';
import { bytesToHex, hexToAscii, asciiToHex } from './format';
import { fromWei, toWei } from './wei';
import { sha3 } from './sha3';
import { isArray, isFunction, isHex, isInstanceOf, isString } from './types';
Expand All @@ -30,7 +30,7 @@ export default {
isInstanceOf,
isString,
bytesToHex,
hex2Ascii,
hexToAscii,
asciiToHex,
createIdentityImg,
decodeCallData,
Expand Down
16 changes: 6 additions & 10 deletions js/src/api/util/sha3.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,17 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

import CryptoJS from 'crypto-js';
import CryptoSha3 from 'crypto-js/sha3';
import { keccak_256 } from 'js-sha3'; // eslint-disable-line

import { hexToBytes } from './format';

export function sha3 (value, options) {
if (options && options.encoding === 'hex') {
if (value.length > 2 && value.substr(0, 2) === '0x') {
value = value.substr(2);
}

value = CryptoJS.enc.Hex.parse(value);
const bytes = hexToBytes(value);
return sha3(bytes);
}

const hash = CryptoSha3(value, {
outputLength: 256
}).toString();
const hash = keccak_256(value);

return `0x${hash}`;
}
11 changes: 11 additions & 0 deletions js/src/api/util/sha3.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,16 @@ describe('api/util/sha3', () => {
it('constructs a correct sha3 value', () => {
expect(sha3('jacogr')).to.equal('0x2f4ff4b5a87abbd2edfed699db48a97744e028c7f7ce36444d40d29d792aa4dc');
});

it('constructs a correct sha3 encoded as hex', () => {
const key = '000000000000000000000000391694e7e0b0cce554cb130d723a9d27458f9298' + '0000000000000000000000000000000000000000000000000000000000000001';
expect(sha3(key, { encoding: 'hex' })).to.equal('0x6661e9d6d8b923d5bbaab1b96e1dd51ff6ea2a93520fdc9eb75d059238b8c5e9');
expect(sha3(`0x${key}`, { encoding: 'hex' })).to.equal('0x6661e9d6d8b923d5bbaab1b96e1dd51ff6ea2a93520fdc9eb75d059238b8c5e9');
});

it('constructs a correct sha3 from Uint8Array', () => {
expect(sha3('01020304', { encoding: 'hex' })).to.equal('0xa6885b3731702da62e8e4a8f584ac46a7f6822f4e2ba50fba902f67b1588d23b');
expect(sha3(Uint8Array.from([1, 2, 3, 4]))).to.equal('0xa6885b3731702da62e8e4a8f584ac46a7f6822f4e2ba50fba902f67b1588d23b');
});
});
});
6 changes: 3 additions & 3 deletions js/src/contracts/badgereg.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

import { bytesToHex, hex2Ascii } from '~/api/util/format';
import { bytesToHex, hexToAscii } from '~/api/util/format';

import ABI from './abi/certifier.json';

Expand Down Expand Up @@ -62,7 +62,7 @@ export default class BadgeReg {
name = bytesToHex(name);
name = name === ZERO32
? null
: hex2Ascii(name);
: hexToAscii(name);

return this.fetchMeta(id)
.then(({ title, icon }) => {
Expand All @@ -84,7 +84,7 @@ export default class BadgeReg {
})
.then(([ title, icon ]) => {
title = bytesToHex(title);
title = title === ZERO32 ? null : hex2Ascii(title);
title = title === ZERO32 ? null : hexToAscii(title);

if (bytesToHex(icon) === ZERO32) {
icon = null;
Expand Down
2 changes: 1 addition & 1 deletion js/src/ui/MethodDecoding/methodDecoding.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ class MethodDecoding extends Component {
getAscii () {
const { api } = this.context;
const { transaction } = this.props;
const ascii = api.util.hex2Ascii(transaction.input || transaction.data);
const ascii = api.util.hexToAscii(transaction.input || transaction.data);

return { value: ascii, valid: ASCII_INPUT.test(ascii) };
}
Expand Down
2 changes: 1 addition & 1 deletion js/src/util/wallet.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

import scrypt from 'scryptsy';
import Transaction from 'ethereumjs-tx';
import * as Transaction from 'ethereumjs-tx';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

import { pbkdf2Sync } from 'crypto';
import { createDecipheriv } from 'browserify-aes';

Expand Down