Skip to content

Commit 3c48163

Browse files
joYyHackArvolear
andauthored
RSAPSS SHA512 (#9)
* RSAPSS SHA512 * fix sa * Adjustments * Adjustment * clean up * fix test --------- Co-authored-by: Artem Chystiakov <artem.ch31@gmail.com>
1 parent 282b042 commit 3c48163

File tree

22 files changed

+594
-204
lines changed

22 files changed

+594
-204
lines changed

contracts/certificate/dispatchers/CRSASHA2Dispatcher.sol renamed to contracts/certificate/dispatchers/CRSADispatcher.sol

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,13 @@ import {PoseidonUnit5L} from "@iden3/contracts/lib/Poseidon.sol";
66
import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
77

88
import {ICertificateDispatcher} from "../../interfaces/dispatchers/ICertificateDispatcher.sol";
9-
10-
import {CRSASHA2Signer} from "../signers/CRSASHA2Signer.sol";
9+
import {ICertificateRSASigner} from "../../interfaces/signers/ICertificateRSASigner.sol";
1110

1211
import {Bytes2Poseidon} from "../../utils/Bytes2Poseidon.sol";
1312
import {RSA} from "../../utils/RSA.sol";
1413
import {X509} from "../../utils/X509.sol";
1514

16-
contract CRSASHA2Dispatcher is ICertificateDispatcher, Initializable {
15+
contract CRSADispatcher is ICertificateDispatcher, Initializable {
1716
using Bytes2Poseidon for bytes;
1817
using X509 for bytes;
1918
using RSA for bytes;
@@ -23,7 +22,7 @@ contract CRSASHA2Dispatcher is ICertificateDispatcher, Initializable {
2322

2423
address public signer;
2524

26-
function __CRSASHA2Dispatcher_init(
25+
function __CRSADispatcher_init(
2726
address signer_,
2827
uint256 keyByteLength_,
2928
bytes calldata keyCheckPrefix_
@@ -42,7 +41,7 @@ contract CRSASHA2Dispatcher is ICertificateDispatcher, Initializable {
4241
bytes memory icaoMemberKey_
4342
) external view override returns (bool) {
4443
return
45-
CRSASHA2Signer(signer).verifyICAOSignature(
44+
ICertificateRSASigner(signer).verifyICAOSignature(
4645
x509SignedAttributes_,
4746
icaoMemberSignature_,
4847
icaoMemberKey_

contracts/certificate/signers/CRSAPSSSHA2Signer.sol renamed to contracts/certificate/signers/CRSAPSSSigner.sol

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,17 @@ pragma solidity 0.8.16;
33

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

6-
import {RSAPSS} from "../../utils/RSAPSS.sol";
6+
import {ICertificateRSASigner} from "../../interfaces/signers/ICertificateRSASigner.sol";
77

8-
contract CRSAPSSSHA2Signer is Initializable {
9-
using RSAPSS for bytes;
8+
import {RSAPSS} from "../../utils/RSAPSS.sol";
109

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

13-
function __CRSAPSSSHA2Signer_init(uint256 exponent_) external initializer {
14+
function __CRSAPSSSigner_init(uint256 exponent_, bool isSha2_) external initializer {
1415
exponent = exponent_;
16+
isSha2 = isSha2_;
1517
}
1618

1719
/**
@@ -21,12 +23,14 @@ contract CRSAPSSSHA2Signer is Initializable {
2123
bytes memory x509SignedAttributes_,
2224
bytes memory icaoMemberSignature_,
2325
bytes memory icaoMemberKey_
24-
) external view returns (bool) {
26+
) external view override returns (bool) {
2527
return
26-
x509SignedAttributes_.verify(
28+
RSAPSS.verify(
29+
x509SignedAttributes_,
2730
icaoMemberSignature_,
2831
abi.encodePacked(exponent),
29-
icaoMemberKey_
32+
icaoMemberKey_,
33+
isSha2
3034
);
3135
}
3236
}

contracts/certificate/signers/CRSASHA2Signer.sol

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@ pragma solidity 0.8.16;
33

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

6+
import {ICertificateRSASigner} from "../../interfaces/signers/ICertificateRSASigner.sol";
7+
68
import {RSA} from "../../utils/RSA.sol";
79
import {SHA1} from "../../utils/SHA1.sol";
810

9-
contract CRSASHA2Signer is Initializable {
11+
contract CRSASHA2Signer is ICertificateRSASigner, Initializable {
1012
using RSA for bytes;
1113

1214
uint256 public exponent; // RSA exponent
@@ -24,7 +26,7 @@ contract CRSASHA2Signer is Initializable {
2426
bytes memory x509SignedAttributes_,
2527
bytes memory icaoMemberSignature_,
2628
bytes memory icaoMemberKey_
27-
) external view returns (bool) {
29+
) external view override returns (bool) {
2830
bytes32 x509SAHash = sha256(x509SignedAttributes_);
2931

3032
bytes memory decrypted_ = icaoMemberSignature_.decrypt(
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity 0.8.16;
3+
4+
/**
5+
* @notice Certificate signer interface
6+
*/
7+
interface ICertificateRSASigner {
8+
function verifyICAOSignature(
9+
bytes calldata x509SignedAttributes_,
10+
bytes calldata icaoMemberSignature_,
11+
bytes calldata icaoMemberKey_
12+
) external view returns (bool);
13+
}

contracts/registration/types.sol

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ pragma solidity 0.8.16;
44
bytes32 constant C_RSA_4096 = keccak256("C_RSA_4096");
55
bytes32 constant C_RSA_2048 = keccak256("C_RSA_2048");
66
bytes32 constant C_RSAPSS_4096 = keccak256("C_RSAPSS_4096");
7+
bytes32 constant C_RSAPSS_SHA512_4096 = keccak256("C_RSAPSS_SHA512_4096");
78

89
bytes32 constant P_NO_AA = keccak256("P_NO_AA");
910
bytes32 constant P_RSA_SHA1_2688 = keccak256("P_RSA_SHA1_2688");

contracts/utils/RSAPSS.sol

Lines changed: 50 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,15 @@
22
pragma solidity 0.8.16;
33

44
import {RSA} from "./RSA.sol";
5+
import {SHA512} from "./SHA512.sol";
56

67
library RSAPSS {
7-
uint256 constant HASH_LEN = 32;
8-
uint256 constant SALT_LEN = 32;
8+
struct HashStruct {
9+
uint256 hashLength;
10+
uint256 saltLength;
11+
function(bytes memory) internal pure returns (bytes memory) hash;
12+
}
13+
914
uint256 constant MS_BITS = 4095 & 7;
1015
uint256 constant MS_BYTES = 512;
1116

@@ -16,48 +21,57 @@ library RSAPSS {
1621
bytes memory message_,
1722
bytes memory s_,
1823
bytes memory e_,
19-
bytes memory n_
24+
bytes memory n_,
25+
bool isSha2_
2026
) internal view returns (bool) {
2127
if (s_.length == 0 || e_.length == 0 || n_.length == 0) {
2228
return false;
2329
}
2430

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

27-
return pss(message_, decipher_);
33+
return pss(message_, decipher_, isSha2_);
2834
}
2935

30-
function pss(bytes memory message_, bytes memory signature_) private pure returns (bool) {
36+
function pss(
37+
bytes memory message_,
38+
bytes memory signature_,
39+
bool isSha2_
40+
) private pure returns (bool) {
41+
HashStruct memory hashStruct = getHashStruct(isSha2_);
42+
uint256 hashLength = hashStruct.hashLength;
43+
uint256 saltLength = hashStruct.saltLength;
44+
3145
if (message_.length > 2 ** 61 - 1) {
3246
return false;
3347
}
3448

35-
bytes32 messageHash_ = sha256(message_);
49+
bytes memory messageHash_ = hashStruct.hash(message_);
3650

37-
if (MS_BYTES < HASH_LEN + SALT_LEN + 2) {
51+
if (MS_BYTES < hashLength + saltLength + 2) {
3852
return false;
3953
}
4054

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

45-
bytes memory db_ = new bytes(MS_BYTES - HASH_LEN - 1);
46-
bytes memory h_ = new bytes(HASH_LEN);
59+
bytes memory db_ = new bytes(MS_BYTES - hashLength - 1);
60+
bytes memory h_ = new bytes(hashLength);
4761

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

52-
for (uint256 i = 0; i < HASH_LEN; ++i) {
66+
for (uint256 i = 0; i < hashLength; ++i) {
5367
h_[i] = signature_[i + db_.length];
5468
}
5569

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

60-
bytes memory dbMask_ = mgf(h_, db_.length);
74+
bytes memory dbMask_ = mgf(h_, db_.length, hashStruct);
6175

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

82-
bytes memory salt_ = new bytes(SALT_LEN);
96+
bytes memory salt_ = new bytes(saltLength);
8397

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

88-
bytes32 hh_ = sha256(abi.encodePacked(hex"0000000000000000", messageHash_, salt_));
102+
bytes memory hh_ = hashStruct.hash(
103+
abi.encodePacked(hex"0000000000000000", messageHash_, salt_)
104+
);
89105

90-
if (bytes32(h_) != hh_) {
106+
if (keccak256(h_) != keccak256(hh_)) {
91107
return false;
92108
}
93109

@@ -96,19 +112,22 @@ library RSAPSS {
96112

97113
function mgf(
98114
bytes memory message_,
99-
uint256 maskLen_
115+
uint256 maskLen_,
116+
HashStruct memory hashStruct_
100117
) private pure returns (bytes memory res_) {
118+
uint256 hashLength = hashStruct_.hashLength;
119+
101120
bytes memory cnt_ = new bytes(4);
102121

103-
require(maskLen_ <= (2 ** 32) * HASH_LEN, "RSAPSS: mask too lengthy");
122+
require(maskLen_ <= (2 ** 32) * hashLength, "RSAPSS: mask too lengthy");
104123

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

111-
bytes32 hashedResInter_ = sha256(abi.encodePacked(message_, cnt_));
130+
bytes memory hashedResInter_ = hashStruct_.hash(abi.encodePacked(message_, cnt_));
112131

113132
res_ = abi.encodePacked(res_, hashedResInter_);
114133
}
@@ -117,4 +136,17 @@ library RSAPSS {
117136
mstore(res_, maskLen_)
118137
}
119138
}
139+
140+
function getHashStruct(bool isSha2_) private pure returns (HashStruct memory) {
141+
return
142+
HashStruct({
143+
hashLength: isSha2_ ? 32 : 64,
144+
saltLength: isSha2_ ? 32 : 64,
145+
hash: isSha2_ ? sha2 : SHA512.sha512
146+
});
147+
}
148+
149+
function sha2(bytes memory data) private pure returns (bytes memory) {
150+
return abi.encodePacked(sha256(data));
151+
}
120152
}

0 commit comments

Comments
 (0)