Skip to content

Commit 61321db

Browse files
committed
Add SHA-512/256 hash operation
1 parent 77277ad commit 61321db

12 files changed

+159
-127
lines changed

go/ops.go

+4
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,10 @@ func doHash(hashOp HashOp, preimage []byte) ([]byte, error) {
131131
hash := crypto.RIPEMD160.New()
132132
hash.Write(tmp)
133133
return hash.Sum(nil), nil
134+
case HashOp_SHA512_256:
135+
hash := crypto.SHA512_256.New()
136+
hash.Write(preimage)
137+
return hash.Sum(nil), nil
134138
}
135139
return nil, errors.Errorf("Unsupported hashop: %d", hashOp)
136140
}

go/ops_test.go

+6
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,12 @@ func TestDoHash(t *testing.T) {
199199
// echo -n c1f026582fe6e8cb620d0c85a72fe421ddded756662a8ec00ed4c297ad10676b | xxd -r -p | openssl dgst -rmd160 -hex
200200
expectedHash: "0bcb587dfb4fc10b36d57f2bba1878f139b75d24",
201201
},
202+
"sha512_256": {
203+
hashOp: HashOp_SHA512_256,
204+
preimage: "food",
205+
// echo -n food | openssl dgst -sha512-256 -hex | cut -d' ' -f2
206+
expectedHash: "5b3a452a6acbf1fc1e553a40c501585d5bd3cca176d562e0a0e19a3c43804e88",
207+
},
202208
}
203209

204210
for name, tc := range cases {

go/proofs.pb.go

+88-124
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

js/package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
"dependencies": {
4848
"protobufjs": "^6.8.8",
4949
"ripemd160": "^2.0.2",
50-
"sha.js": "^2.4.11"
50+
"sha.js": "^2.4.11",
51+
"js-sha512": "^0.8.0"
5152
}
5253
}

js/src/generated/codecimpl.d.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ export namespace ics23 {
88
SHA512 = 2,
99
KECCAK = 3,
1010
RIPEMD160 = 4,
11-
BITCOIN = 5
11+
BITCOIN = 5,
12+
SHA512_256 = 6
1213
}
1314

1415
/**

js/src/generated/codecimpl.js

+27
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ $root.ics23 = (function() {
2828
* @property {number} KECCAK=3 KECCAK value
2929
* @property {number} RIPEMD160=4 RIPEMD160 value
3030
* @property {number} BITCOIN=5 BITCOIN value
31+
* @property {number} SHA512_256=6 SHA512_256 value
3132
*/
3233
ics23.HashOp = (function() {
3334
var valuesById = {}, values = Object.create(valuesById);
@@ -37,6 +38,7 @@ $root.ics23 = (function() {
3738
values[valuesById[3] = "KECCAK"] = 3;
3839
values[valuesById[4] = "RIPEMD160"] = 4;
3940
values[valuesById[5] = "BITCOIN"] = 5;
41+
values[valuesById[6] = "SHA512_256"] = 6;
4042
return values;
4143
})();
4244

@@ -1161,6 +1163,7 @@ $root.ics23 = (function() {
11611163
case 3:
11621164
case 4:
11631165
case 5:
1166+
case 6:
11641167
break;
11651168
}
11661169
if (message.prehashKey != null && message.hasOwnProperty("prehashKey"))
@@ -1173,6 +1176,7 @@ $root.ics23 = (function() {
11731176
case 3:
11741177
case 4:
11751178
case 5:
1179+
case 6:
11761180
break;
11771181
}
11781182
if (message.prehashValue != null && message.hasOwnProperty("prehashValue"))
@@ -1185,6 +1189,7 @@ $root.ics23 = (function() {
11851189
case 3:
11861190
case 4:
11871191
case 5:
1192+
case 6:
11881193
break;
11891194
}
11901195
if (message.length != null && message.hasOwnProperty("length"))
@@ -1245,6 +1250,10 @@ $root.ics23 = (function() {
12451250
case 5:
12461251
message.hash = 5;
12471252
break;
1253+
case "SHA512_256":
1254+
case 6:
1255+
message.hash = 6;
1256+
break;
12481257
}
12491258
switch (object.prehashKey) {
12501259
case "NO_HASH":
@@ -1271,6 +1280,10 @@ $root.ics23 = (function() {
12711280
case 5:
12721281
message.prehashKey = 5;
12731282
break;
1283+
case "SHA512_256":
1284+
case 6:
1285+
message.prehashKey = 6;
1286+
break;
12741287
}
12751288
switch (object.prehashValue) {
12761289
case "NO_HASH":
@@ -1297,6 +1310,10 @@ $root.ics23 = (function() {
12971310
case 5:
12981311
message.prehashValue = 5;
12991312
break;
1313+
case "SHA512_256":
1314+
case 6:
1315+
message.prehashValue = 6;
1316+
break;
13001317
}
13011318
switch (object.length) {
13021319
case "NO_PREFIX":
@@ -1579,6 +1596,7 @@ $root.ics23 = (function() {
15791596
case 3:
15801597
case 4:
15811598
case 5:
1599+
case 6:
15821600
break;
15831601
}
15841602
if (message.prefix != null && message.hasOwnProperty("prefix"))
@@ -1627,6 +1645,10 @@ $root.ics23 = (function() {
16271645
case 5:
16281646
message.hash = 5;
16291647
break;
1648+
case "SHA512_256":
1649+
case 6:
1650+
message.hash = 6;
1651+
break;
16301652
}
16311653
if (object.prefix != null)
16321654
if (typeof object.prefix === "string")
@@ -2208,6 +2230,7 @@ $root.ics23 = (function() {
22082230
case 3:
22092231
case 4:
22102232
case 5:
2233+
case 6:
22112234
break;
22122235
}
22132236
return null;
@@ -2268,6 +2291,10 @@ $root.ics23 = (function() {
22682291
case 5:
22692292
message.hash = 5;
22702293
break;
2294+
case "SHA512_256":
2295+
case 6:
2296+
message.hash = 6;
2297+
break;
22712298
}
22722299
return message;
22732300
};

js/src/ops.spec.ts

+10
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,16 @@ describe("applyLeaf", () => {
5050
expect(applyLeaf(op, key, value)).toEqual(expected);
5151
});
5252

53+
it("hashes food with sha-512/256", () => {
54+
const op: ics23.ILeafOp = { hash: ics23.HashOp.SHA512_256 };
55+
const key = toAscii("fo");
56+
const value = toAscii("od");
57+
const expected = fromHex(
58+
"5b3a452a6acbf1fc1e553a40c501585d5bd3cca176d562e0a0e19a3c43804e88"
59+
);
60+
expect(applyLeaf(op, key, value)).toEqual(expected);
61+
});
62+
5363
it("hashes foobar (different breakpoint)", () => {
5464
const op: ics23.ILeafOp = { hash: ics23.HashOp.SHA256 };
5565
const key = toAscii("f");

js/src/ops.ts

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { sha512_256 } from "js-sha512";
12
import ripemd160 from "ripemd160";
23
import shajs from "sha.js";
34

@@ -109,6 +110,8 @@ export function doHash(hashOp: ics23.HashOp, preimage: Uint8Array): Uint8Array {
109110
return rp160(preimage);
110111
case ics23.HashOp.BITCOIN:
111112
return rp160(s256(preimage));
113+
case ics23.HashOp.SHA512_256:
114+
return new Uint8Array(sha512_256.arrayBuffer(preimage));
112115
}
113116
throw new Error(`Unsupported hashop: ${hashOp}`);
114117
}

js/yarn.lock

+5
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,11 @@ jasmine@^3.5.0:
305305
glob "^7.1.4"
306306
jasmine-core "~3.5.0"
307307

308+
js-sha512@^0.8.0:
309+
version "0.8.0"
310+
resolved "https://registry.yarnpkg.com/js-sha512/-/js-sha512-0.8.0.tgz#dd22db8d02756faccf19f218e3ed61ec8249f7d4"
311+
integrity sha512-PWsmefG6Jkodqt+ePTvBZCSMFgN7Clckjd0O7su3I0+BW2QWUTJNzjktHsztGLhncP2h8mcF9V9Y2Ha59pAViQ==
312+
308313
js-tokens@^4.0.0:
309314
version "4.0.0"
310315
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"

proofs.proto

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ enum HashOp {
1010
KECCAK = 3;
1111
RIPEMD160 = 4;
1212
BITCOIN = 5; // ripemd160(sha256(x))
13+
SHA512_256 = 6;
1314
}
1415

1516
/**

rust/src/ics23.rs

+1
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,7 @@ pub enum HashOp {
252252
Ripemd160 = 4,
253253
/// ripemd160(sha256(x))
254254
Bitcoin = 5,
255+
Sha512_256 = 6,
255256
}
256257
///*
257258
///LengthOp defines how to process the key and value of the LeafOp

rust/src/ops.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use anyhow::{bail, ensure};
22
use ripemd160::Ripemd160;
3-
use sha2::{Digest, Sha256, Sha512};
3+
use sha2::{Digest, Sha256, Sha512, Sha512Trunc256};
44
use sha3::Sha3_512;
55
use std::convert::TryInto;
66

@@ -41,6 +41,7 @@ fn do_hash(hash: HashOp, data: &[u8]) -> Result<Hash> {
4141
HashOp::Bitcoin => Ok(Hash::from(
4242
Ripemd160::digest(Sha256::digest(data).as_slice()).as_slice(),
4343
)),
44+
HashOp::Sha512_256 => Ok(Hash::from(Sha512Trunc256::digest(data).as_slice())),
4445
}
4546
}
4647

@@ -99,6 +100,14 @@ mod tests {
99100
"bitcoin hash fails"
100101
);
101102

103+
let hash = do_hash(HashOp::Sha512_256, b"food")?;
104+
ensure!(
105+
hash == hex::decode(
106+
"5b3a452a6acbf1fc1e553a40c501585d5bd3cca176d562e0a0e19a3c43804e88"
107+
)?,
108+
"sha512/256 hash fails"
109+
);
110+
102111
Ok(())
103112
}
104113

0 commit comments

Comments
 (0)