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

RSAPSS SHA512 #9

Merged
merged 6 commits into from
Aug 13, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@ import {PoseidonUnit5L} from "@iden3/contracts/lib/Poseidon.sol";
import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";

import {ICertificateDispatcher} from "../../interfaces/dispatchers/ICertificateDispatcher.sol";

import {CRSASHA2Signer} from "../signers/CRSASHA2Signer.sol";
import {ICertificateRSASigner} from "../../interfaces/signers/ICertificateRSASigner.sol";

import {Bytes2Poseidon} from "../../utils/Bytes2Poseidon.sol";
import {RSA} from "../../utils/RSA.sol";
import {X509} from "../../utils/X509.sol";

contract CRSASHA2Dispatcher is ICertificateDispatcher, Initializable {
contract CRSADispatcher is ICertificateDispatcher, Initializable {
using Bytes2Poseidon for bytes;
using X509 for bytes;
using RSA for bytes;
Expand All @@ -23,7 +22,7 @@ contract CRSASHA2Dispatcher is ICertificateDispatcher, Initializable {

address public signer;

function __CRSASHA2Dispatcher_init(
function __CRSADispatcher_init(
address signer_,
uint256 keyByteLength_,
bytes calldata keyCheckPrefix_
Expand All @@ -42,7 +41,7 @@ contract CRSASHA2Dispatcher is ICertificateDispatcher, Initializable {
bytes memory icaoMemberKey_
) external view override returns (bool) {
return
CRSASHA2Signer(signer).verifyICAOSignature(
ICertificateRSASigner(signer).verifyICAOSignature(
x509SignedAttributes_,
icaoMemberSignature_,
icaoMemberKey_
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@ pragma solidity 0.8.16;

import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";

import {RSAPSS} from "../../utils/RSAPSS.sol";
import {ICertificateRSASigner} from "../../interfaces/signers/ICertificateRSASigner.sol";

contract CRSAPSSSHA2Signer is Initializable {
using RSAPSS for bytes;
import {RSAPSS} from "../../utils/RSAPSS.sol";

contract CRSAPSSSigner is ICertificateRSASigner, Initializable {
uint256 public exponent; // RSAPSS exponent
bool public isSha2; // hash function switcher, true - sha2, false - sha512

function __CRSAPSSSHA2Signer_init(uint256 exponent_) external initializer {
function __CRSAPSSSigner_init(uint256 exponent_, bool isSha2_) external initializer {
exponent = exponent_;
isSha2 = isSha2_;
}

/**
Expand All @@ -21,12 +23,14 @@ contract CRSAPSSSHA2Signer is Initializable {
bytes memory x509SignedAttributes_,
bytes memory icaoMemberSignature_,
bytes memory icaoMemberKey_
) external view returns (bool) {
) external view override returns (bool) {
return
x509SignedAttributes_.verify(
RSAPSS.verify(
x509SignedAttributes_,
icaoMemberSignature_,
abi.encodePacked(exponent),
icaoMemberKey_
icaoMemberKey_,
isSha2
);
}
}
6 changes: 4 additions & 2 deletions contracts/certificate/signers/CRSASHA2Signer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ pragma solidity 0.8.16;

import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";

import {ICertificateRSASigner} from "../../interfaces/signers/ICertificateRSASigner.sol";

import {RSA} from "../../utils/RSA.sol";
import {SHA1} from "../../utils/SHA1.sol";

contract CRSASHA2Signer is Initializable {
contract CRSASHA2Signer is ICertificateRSASigner, Initializable {
using RSA for bytes;

uint256 public exponent; // RSA exponent
Expand All @@ -24,7 +26,7 @@ contract CRSASHA2Signer is Initializable {
bytes memory x509SignedAttributes_,
bytes memory icaoMemberSignature_,
bytes memory icaoMemberKey_
) external view returns (bool) {
) external view override returns (bool) {
bytes32 x509SAHash = sha256(x509SignedAttributes_);

bytes memory decrypted_ = icaoMemberSignature_.decrypt(
Expand Down
13 changes: 13 additions & 0 deletions contracts/interfaces/signers/ICertificateRSASigner.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.16;

/**
* @notice Certificate signer interface
*/
interface ICertificateRSASigner {
function verifyICAOSignature(
bytes calldata x509SignedAttributes_,
bytes calldata icaoMemberSignature_,
bytes calldata icaoMemberKey_
) external view returns (bool);
}
1 change: 1 addition & 0 deletions contracts/registration/types.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pragma solidity 0.8.16;
bytes32 constant C_RSA_4096 = keccak256("C_RSA_4096");
bytes32 constant C_RSA_2048 = keccak256("C_RSA_2048");
bytes32 constant C_RSAPSS_4096 = keccak256("C_RSAPSS_4096");
bytes32 constant C_RSAPSS_SHA512_4096 = keccak256("C_RSAPSS_SHA512_4096");

bytes32 constant P_NO_AA = keccak256("P_NO_AA");
bytes32 constant P_RSA_SHA1_2688 = keccak256("P_RSA_SHA1_2688");
Expand Down
68 changes: 50 additions & 18 deletions contracts/utils/RSAPSS.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,15 @@
pragma solidity 0.8.16;

import {RSA} from "./RSA.sol";
import {SHA512} from "./SHA512.sol";

library RSAPSS {
uint256 constant HASH_LEN = 32;
uint256 constant SALT_LEN = 32;
struct HashStruct {
uint256 hashLength;
uint256 saltLength;
function(bytes memory) internal pure returns (bytes memory) hash;
}

uint256 constant MS_BITS = 4095 & 7;
uint256 constant MS_BYTES = 512;

Expand All @@ -16,48 +21,57 @@ library RSAPSS {
bytes memory message_,
bytes memory s_,
bytes memory e_,
bytes memory n_
bytes memory n_,
bool isSha2_
) internal view returns (bool) {
if (s_.length == 0 || e_.length == 0 || n_.length == 0) {
return false;
}

bytes memory decipher_ = RSA.decrypt(s_, e_, n_);

return pss(message_, decipher_);
return pss(message_, decipher_, isSha2_);
}

function pss(bytes memory message_, bytes memory signature_) private pure returns (bool) {
function pss(
bytes memory message_,
bytes memory signature_,
bool isSha2_
) private pure returns (bool) {
HashStruct memory hashStruct = getHashStruct(isSha2_);
uint256 hashLength = hashStruct.hashLength;
uint256 saltLength = hashStruct.saltLength;

if (message_.length > 2 ** 61 - 1) {
return false;
}

bytes32 messageHash_ = sha256(message_);
bytes memory messageHash_ = hashStruct.hash(message_);

if (MS_BYTES < HASH_LEN + SALT_LEN + 2) {
if (MS_BYTES < hashLength + saltLength + 2) {
return false;
}

if (signature_[MS_BYTES - 1] != hex"BC") {
return false;
}

bytes memory db_ = new bytes(MS_BYTES - HASH_LEN - 1);
bytes memory h_ = new bytes(HASH_LEN);
bytes memory db_ = new bytes(MS_BYTES - hashLength - 1);
bytes memory h_ = new bytes(hashLength);

for (uint256 i = 0; i < db_.length; ++i) {
db_[i] = signature_[i];
}

for (uint256 i = 0; i < HASH_LEN; ++i) {
for (uint256 i = 0; i < hashLength; ++i) {
h_[i] = signature_[i + db_.length];
}

if (uint8(db_[0] & bytes1(uint8(((0xFF << (MS_BITS)))))) == 1) {
return false;
}

bytes memory dbMask_ = mgf(h_, db_.length);
bytes memory dbMask_ = mgf(h_, db_.length, hashStruct);

for (uint256 i = 0; i < db_.length; ++i) {
db_[i] ^= dbMask_[i];
Expand All @@ -79,15 +93,17 @@ library RSAPSS {
return false;
}

bytes memory salt_ = new bytes(SALT_LEN);
bytes memory salt_ = new bytes(saltLength);

for (uint256 i = 0; i < salt_.length; ++i) {
salt_[i] = db_[db_.length - salt_.length + i];
}

bytes32 hh_ = sha256(abi.encodePacked(hex"0000000000000000", messageHash_, salt_));
bytes memory hh_ = hashStruct.hash(
abi.encodePacked(hex"0000000000000000", messageHash_, salt_)
);

if (bytes32(h_) != hh_) {
if (keccak256(h_) != keccak256(hh_)) {
return false;
}

Expand All @@ -96,19 +112,22 @@ library RSAPSS {

function mgf(
bytes memory message_,
uint256 maskLen_
uint256 maskLen_,
HashStruct memory hashStruct_
) private pure returns (bytes memory res_) {
uint256 hashLength = hashStruct_.hashLength;

bytes memory cnt_ = new bytes(4);

require(maskLen_ <= (2 ** 32) * HASH_LEN, "RSAPSS: mask too lengthy");
require(maskLen_ <= (2 ** 32) * hashLength, "RSAPSS: mask too lengthy");

for (uint256 i = 0; i < (maskLen_ + HASH_LEN - 1) / HASH_LEN; ++i) {
for (uint256 i = 0; i < (maskLen_ + hashLength - 1) / hashLength; ++i) {
cnt_[0] = bytes1(uint8((i >> 24) & 255));
cnt_[1] = bytes1(uint8((i >> 16) & 255));
cnt_[2] = bytes1(uint8((i >> 8) & 255));
cnt_[3] = bytes1(uint8(i & 255));

bytes32 hashedResInter_ = sha256(abi.encodePacked(message_, cnt_));
bytes memory hashedResInter_ = hashStruct_.hash(abi.encodePacked(message_, cnt_));

res_ = abi.encodePacked(res_, hashedResInter_);
}
Expand All @@ -117,4 +136,17 @@ library RSAPSS {
mstore(res_, maskLen_)
}
}

function getHashStruct(bool isSha2_) private pure returns (HashStruct memory) {
return
HashStruct({
hashLength: isSha2_ ? 32 : 64,
saltLength: isSha2_ ? 32 : 64,
hash: isSha2_ ? sha2 : SHA512.sha512
});
}

function sha2(bytes memory data) private pure returns (bytes memory) {
return abi.encodePacked(sha256(data));
}
}
Loading
Loading