-
Notifications
You must be signed in to change notification settings - Fork 145
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #784 from o1-labs/feature/ecdsa-keccak-overview
Keccak overview
- Loading branch information
Showing
2 changed files
with
168 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
--- | ||
title: Keccak | ||
hide_title: true | ||
description: A comprehensive guide on how to use Keccak-based hashes in o1js. | ||
keywords: | ||
- keccak | ||
- sha3 | ||
- hash | ||
- ethereum | ||
- mina blockchain | ||
- blockchain technology | ||
- data structures | ||
--- | ||
|
||
:::info | ||
|
||
Please note that zkApp programmability is not yet available on Mina Mainnet, but zkApps can now be deployed to Berkeley Testnet. | ||
|
||
::: | ||
|
||
# Keccak (SHA-3) | ||
|
||
Keccak is a flexible cryptographic hash function that provides more security than traditional SHA hash algorithms. | ||
|
||
## What is Keccak? | ||
|
||
Developed by a team of cryptographers from Belgium, Keccak was the winning submission for the National Institute of Standards and Technology (NIST) SHA-3 competition. Keccak was standardized as SHA-3. Keccak is used in many different applications, including Ethereum. | ||
|
||
Specifically, Keccak is used in the Ethereum ecosystem to hash addresses, transactions, and blocks. It is also used to hash the state trie, the data structure that stores the state of the Ethereum blockchain. | ||
Because of the common usage of Keccak in Ethereum, it is a key component of o1js that you can use to verify Ethereum transactions and blocks in o1js. | ||
|
||
## Keccak and Poseidon | ||
|
||
As an o1js developer, you are likely familar with the [Poseidon](https://o1-labs.github.io/proof-systems/specs/poseidon.html) zero knowledge native hash function. Poseidon operates over the native [Pallas base field](https://electriccoin.co/blog/the-pasta-curves-for-halo-2-and-beyond/) and uses parameters generated specifically for Mina which makes Poseidon the most efficient hash function available in o1js. | ||
|
||
In contrast, Keccak is a hash function that requires binary arithmetic. It operates over binary data and is not native to most zero knowledge proofs. For this reason, Keccak is not as efficient as Poseidon, but it is still very useful for verifying Ethereum transactions and blocks. | ||
So, when you choose what hash function to use, it is important to consider the use case and the data that needs to be hashed. | ||
|
||
## Basic usage | ||
|
||
Keccak is available in the following configurations that are available under the `Hash` namespace in o1js: | ||
|
||
- `Hash.SHA3_256`: NIST SHA3 hash function with output size of 256 bits. | ||
- `Hash.SHA3_385`: NIST SHA3 hash function with output size of 384 bits. | ||
- `Hash.SHA3_512`: NIST SHA3 hash function with output size of 512 bits. | ||
- `Hash.Keccak256`: pre-NIST Keccak hash function with output size of 256 bits. _This configuration used to hash blocks, transactions, and more in Ethereum._ | ||
- `Hash.Keccak384`: pre-NIST Keccak hash function with output size of 384 bits. | ||
- `Hash.Keccak512`: pre-NIST Keccak hash function with output size of 512 bits. | ||
|
||
Because Keccak operates over binary data instead of native Field elements like Poseidon, o1js uses the `Bytes` type. `Bytes` is a fixed-length array of bytes that can be used to represent binary data. | ||
Under the hood, `Bytes` is represented as an array of `UInt8` elements. | ||
|
||
In order to use `Bytes`, you need to extend the `Bytes` class and specify the length of bytes: | ||
|
||
```ts | ||
// This creates a Bytes class that represents 16 bytes | ||
class Bytes16 extends Bytes(16) {} | ||
``` | ||
|
||
To initiate your `Bytes16` class with a value, you can use `from`, `fromHex`, or `fromString`. | ||
|
||
```ts | ||
// `.from` accepts an array of `number`, `bigint`, `UInt8` elements or a `Uint8Array` or `Bytes` | ||
let bytes = Bytes16.from(new Array(16).fill(0)); | ||
|
||
// converts a hex string to bytes | ||
bytes = Bytes16.fromHex('646f67'); | ||
|
||
// converts a string to bytes | ||
bytes = Bytes16.fromString('dog'); | ||
|
||
// print the contents of `bytes` to the console | ||
bytes.bytes.forEach((b) => console.log(b.toBigInt())); | ||
// [100n, 111n, 103n, 0n, 0n, 0n, 0n, 0n, 0n, 0n, 0n, 0n, 0n, 0n, 0n, 0n] | ||
``` | ||
|
||
:::note | ||
If the input array is smaller than the length of the `Bytes` class, it will be padded with zeros. | ||
::: | ||
|
||
You can also convert a `Bytes` object back to a hex string using `toHex`. | ||
|
||
```ts | ||
class Bytes3 extends Bytes(3) {} | ||
|
||
let bytes = Bytes3.fromHex('646f67'); | ||
let hex = bytes.toHex(); | ||
console.log('hex', hex); | ||
// 646f67 | ||
``` | ||
|
||
Now that you know how to use `Bytes` as input, you can use it to hash data using Keccak: | ||
|
||
```ts | ||
// define a preimage | ||
let preimage = 'The quick brown fox jumps over the lazy dog'; | ||
|
||
// create a Bytes class that represents 43 bytes | ||
class Bytes43 extends Bytes(43) {} | ||
|
||
// convert the preimage to bytes | ||
let preimageBytes = Bytes43.fromString(preimage); | ||
|
||
// hash the preimage | ||
let hash = Hash.SHA3_256.hash(preimageBytes); | ||
|
||
console.log(hash.toHex()); | ||
//69070dda01975c8c120c3aada1b282394e7f032fa9cf32f4cb2259a0897dfc04 | ||
``` | ||
|
||
See the o1js repository for an [example](https://github.com/o1-labs/o1js/tree/main/src/examples/zkapps/hashing) of how to use Keccak. | ||
|
||
### Bytes - API reference | ||
|
||
```ts | ||
// creates a Bytes class that represents n bytes (n is 32 in this example) | ||
let n = 32; | ||
class BytesN extends Bytes(n) {} | ||
|
||
// initiate an instance from a hex string | ||
let bytes = BytesN.fromHex('646f67'); | ||
|
||
// initiate an instance from a string | ||
bytes = BytesN.fromString('dog'); | ||
|
||
// initiate an instance from an array of numbers | ||
bytes = BytesN.from([100, 111, 103]); | ||
|
||
// initiate an instance from an array of bigints | ||
bytes = BytesN.from([100n, 111n, 103n]); | ||
|
||
// initiate an instance from an array of UInt8 elements | ||
bytes = BytesN.from([UInt8(100), UInt8(111), UInt8(103)]); | ||
|
||
// initiate an instance from a Uint8Array | ||
bytes = BytesN.from(new Uint8Array([100, 111, 103])); | ||
|
||
// initiate an instance from another Bytes instance | ||
bytes = BytesN.from(BytesN.fromHex('646f67')); | ||
|
||
// convert the bytes to a hex string | ||
const hex = bytes.toHex(); | ||
``` | ||
|
||
### Keccak - API reference | ||
|
||
```ts | ||
// https://keccak.team/keccak.html hash function, pre-NIST specification | ||
// hash bytes using Keccak256 with output size of 256 bits, mainly used in Ethereum | ||
Hash.Keccak256.hash(bytes); | ||
|
||
// hash bytes using Keccak384 with output size of 384 bits | ||
Hash.Keccak384.hash(bytes); | ||
|
||
// hash bytes using Keccak512 with output size of 512 bits | ||
Keccak.Keccak512.hash(bytes); | ||
|
||
// https://csrc.nist.gov/pubs/fips/202/final hash function, official NIST specification | ||
// hash bytes using SHA3_256 with output size of 256 bits | ||
Hash.SHA3_256.hash(bytes); | ||
|
||
// hash bytes using SHA3_384 with output size of 384 bits | ||
Hash.SHA3_384.hash(bytes); | ||
|
||
// hash bytes using SHA3_512 with output size of 512 bits | ||
Hash.SHA3_512.hash(bytes); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
9206173
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs:
docs2 – ./
docs2-git-main-minadocs.vercel.app
docs2-minadocs.vercel.app
docs.minaprotocol.com
9206173
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs:
07-oracles – ./examples/zkapps/07-oracles/oracle
07-oracles-minadocs.vercel.app
07-oracles-git-main-minadocs.vercel.app
07-oracles.vercel.app