Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

contracts: add SHA384 hash and P-384 curve #217

Merged
merged 3 commits into from
Oct 31, 2023
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
26 changes: 23 additions & 3 deletions contracts/contracts/Sapphire.sol
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ library Sapphire {
0x0100000000000000000000000000000000000101;
address internal constant SHA512 =
0x0100000000000000000000000000000000000102;
address internal constant SHA384 =
matevz marked this conversation as resolved.
Show resolved Hide resolved
0x0100000000000000000000000000000000000103;

type Curve25519PublicKey is bytes32;
type Curve25519SecretKey is bytes32;
Expand All @@ -52,7 +54,9 @@ library Sapphire {
// Sr25519 signature over the provided message.
Sr25519,
// Secp256r1 signature over the provided SHA-256 digest.
Secp256r1PrehashedSha256
Secp256r1PrehashedSha256,
// Secp384r1 signature over the provided SHA-384 digest.
matevz marked this conversation as resolved.
Show resolved Hide resolved
Secp384r1PrehashedSha384
}

/**
Expand Down Expand Up @@ -231,7 +235,7 @@ library Sapphire {
* **not** vulnerable to length-extension attacks.
*
* @custom:standard https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
* @custom:see @oasisprotocol/oasis-sdk :: precompile/sha512.rs :: call_sha512_256
* @custom:see @oasisprotocol/oasis-sdk :: precompile/sha2.rs :: call_sha512_256
* @param input Bytes to hash
* @return result 32 byte digest
*/
Expand All @@ -247,7 +251,7 @@ function sha512_256(bytes memory input) view returns (bytes32 result) {
* Hash the input data with SHA-512
*
* @custom:standard https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
* @custom:see @oasisprotocol/oasis-sdk :: precompile/sha512.rs :: call_sha512
* @custom:see @oasisprotocol/oasis-sdk :: precompile/sha2.rs :: call_sha512
* @param input Bytes to hash
* @return output 64 byte digest
*/
Expand All @@ -258,3 +262,19 @@ function sha512(bytes memory input) view returns (bytes memory output) {

require(success, "sha512");
}

/**
* Hash the input data with SHA-384
*
* @custom:standard https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
* @custom:see @oasisprotocol/oasis-sdk :: precompile/sha2.rs :: call_sha384
* @param input Bytes to hash
* @return output 48 byte digest
*/
function sha384(bytes memory input) view returns (bytes memory output) {
bool success;

(success, output) = Sapphire.SHA384.staticcall(input);

require(success, "sha384");
}
10 changes: 9 additions & 1 deletion contracts/contracts/tests/HashTests.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

pragma solidity ^0.8.0;

import {sha512, sha512_256} from "../Sapphire.sol";
import {sha512, sha512_256, sha384} from "../Sapphire.sol";

contract HashTests {
function testSHA512(bytes memory data)
Expand All @@ -13,6 +13,14 @@ contract HashTests {
return sha512(data);
}

function testSHA384(bytes memory data)
external
view
returns (bytes memory)
{
return sha384(data);
}

function testSHA512_256(bytes memory data) external view returns (bytes32) {
return sha512_256(data);
}
Expand Down
28 changes: 19 additions & 9 deletions contracts/test/hashes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@ import { randomBytes, createHash } from 'crypto';
import { ethers } from 'hardhat';
import { HashTests } from '../typechain-types/contracts/tests/HashTests';
import { HashTests__factory } from '../typechain-types/factories/contracts/tests';
import { PromiseOrValue } from '../typechain-types/common';
import { BytesLike, CallOverrides } from 'ethers';

type HasherTestT = (
data: PromiseOrValue<BytesLike>,
overrides?: CallOverrides | undefined,
) => Promise<string>;

describe('Hashes', () => {
let contract: HashTests;
Expand All @@ -15,21 +22,24 @@ describe('Hashes', () => {
await contract.deployed();
});

it('SHA512/256', async () => {
async function testHashes(algname: string, method: HasherTestT) {
for (let i = 0; i < 512; i += 64) {
const data = randomBytes(i);
const hash = createHash('SHA512-256').update(data).digest('hex');
const result = await contract.testSHA512_256(data);
const hash = createHash(algname).update(data).digest('hex');
const result = await method(data);
expect(result).eq('0x' + hash);
}
}

it('SHA512-256', async () => {
testHashes('SHA512-256', contract.testSHA512_256.bind(contract));
});

it('SHA512', async () => {
for (let i = 0; i < 512; i += 64) {
const data = randomBytes(i);
const hash = createHash('SHA512').update(data).digest('hex');
const result = await contract.testSHA512(data);
expect(result).eq('0x' + hash);
}
testHashes('SHA512', contract.testSHA512.bind(contract));
});

it('SHA384', async () => {
testHashes('SHA384', contract.testSHA384.bind(contract));
});
});
16 changes: 16 additions & 0 deletions contracts/test/signing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ const VARYING_SIZED_BUFFERS = [
randomBytes(1),
randomBytes(16),
randomBytes(32),
randomBytes(48),
randomBytes(64),
];

Expand Down Expand Up @@ -213,4 +214,19 @@ describe('Signing', function () {
0,
);
});

it('Secp384r1 (Prehashed SHA384)', async () => {
// Try Secp384r1 (alg=8)
// 48 byte context, empty message
const sha384_kp = await se.testKeygen(8, randomBytes(48));
await testSignThenVerify(
se,
8,
sha384_kp,
randomBytes(48),
EMPTY_BUFFER,
48,
0,
);
});
});