refactor: move brother_node development artifact to dev/test-nodes subdirectory
Development Artifact Cleanup: ✅ BROTHER_NODE REORGANIZATION: Moved development test node to appropriate location - dev/test-nodes/brother_node/: Moved from root directory for better organization - Contains development configuration, test logs, and test chain data - No impact on production systems - purely development/testing artifact ✅ DEVELOPMENT ARTIFACTS IDENTIFIED: - Chain ID: aitbc-brother-chain (test/development chain) - Ports: 8010 (P2P) and 8011 (RPC) - different from production - Environment: .env file with test configuration - Logs: rpc.log and node.log from development testing session (March 15, 2026) ✅ ROOT DIRECTORY CLEANUP: Removed development clutter from production directory - brother_node/ moved to dev/test-nodes/brother_node/ - Root directory now contains only production-ready components - Development artifacts properly organized in dev/ subdirectory DIRECTORY STRUCTURE IMPROVEMENT: 📁 dev/test-nodes/: Development and testing node configurations 🏗️ Root Directory: Clean production structure with only essential components 🧪 Development Isolation: Test environments separated from production BENEFITS: ✅ Clean Production Directory: No development artifacts in root ✅ Better Organization: Development nodes grouped in dev/ subdirectory ✅ Clear Separation: Production vs development environments clearly distinguished ✅ Maintainability: Easier to identify and manage development components RESULT: Successfully moved brother_node development artifact to dev/test-nodes/ subdirectory, cleaning up the root directory while preserving development testing environment for future use.
This commit is contained in:
154
dev/env/node_modules/@openzeppelin/contracts/utils/cryptography/RSA.sol
generated
vendored
Executable file
154
dev/env/node_modules/@openzeppelin/contracts/utils/cryptography/RSA.sol
generated
vendored
Executable file
@@ -0,0 +1,154 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/RSA.sol)
|
||||
pragma solidity ^0.8.20;
|
||||
|
||||
import {Math} from "../math/Math.sol";
|
||||
|
||||
/**
|
||||
* @dev RSA PKCS#1 v1.5 signature verification implementation according to https://datatracker.ietf.org/doc/html/rfc8017[RFC8017].
|
||||
*
|
||||
* This library supports PKCS#1 v1.5 padding to avoid malleability via chosen plaintext attacks in practical implementations.
|
||||
* The padding follows the EMSA-PKCS1-v1_5-ENCODE encoding definition as per section 9.2 of the RFC. This padding makes
|
||||
* RSA semantically secure for signing messages.
|
||||
*
|
||||
* Inspired by https://github.com/adria0/SolRsaVerify/blob/79c6182cabb9102ea69d4a2e996816091d5f1cd1[Adrià Massanet's work] (GNU General Public License v3.0).
|
||||
*
|
||||
* _Available since v5.1._
|
||||
*/
|
||||
library RSA {
|
||||
/**
|
||||
* @dev Same as {pkcs1Sha256} but using SHA256 to calculate the digest of `data`.
|
||||
*/
|
||||
function pkcs1Sha256(
|
||||
bytes memory data,
|
||||
bytes memory s,
|
||||
bytes memory e,
|
||||
bytes memory n
|
||||
) internal view returns (bool) {
|
||||
return pkcs1Sha256(sha256(data), s, e, n);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Verifies a PKCSv1.5 signature given a digest according to the verification
|
||||
* method described in https://datatracker.ietf.org/doc/html/rfc8017#section-8.2.2[section 8.2.2 of RFC8017] with
|
||||
* support for explicit or implicit NULL parameters in the DigestInfo (no other optional parameters are supported).
|
||||
*
|
||||
* IMPORTANT: For security reason, this function requires the signature and modulus to have a length of at least
|
||||
* 2048 bits. If you use a smaller key, consider replacing it with a larger, more secure, one.
|
||||
*
|
||||
* WARNING: This verification algorithm doesn't prevent replayability. If called multiple times with the same
|
||||
* digest, public key and (valid signature), it will return true every time. Consider including an onchain nonce
|
||||
* or unique identifier in the message to prevent replay attacks.
|
||||
*
|
||||
* WARNING: This verification algorithm supports any exponent. NIST recommends using `65537` (or higher).
|
||||
* That is the default value many libraries use, such as OpenSSL. Developers may choose to reject public keys
|
||||
* using a low exponent out of security concerns.
|
||||
*
|
||||
* @param digest the digest to verify
|
||||
* @param s is a buffer containing the signature
|
||||
* @param e is the exponent of the public key
|
||||
* @param n is the modulus of the public key
|
||||
*/
|
||||
function pkcs1Sha256(bytes32 digest, bytes memory s, bytes memory e, bytes memory n) internal view returns (bool) {
|
||||
unchecked {
|
||||
// cache and check length
|
||||
uint256 length = n.length;
|
||||
if (
|
||||
length < 0x100 || // Enforce 2048 bits minimum
|
||||
length != s.length // signature must have the same length as the finite field
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Verify that s < n to ensure there's only one valid signature for a given message
|
||||
for (uint256 i = 0; i < length; i += 0x20) {
|
||||
uint256 p = Math.min(i, length - 0x20);
|
||||
bytes32 sp = _unsafeReadBytes32(s, p);
|
||||
bytes32 np = _unsafeReadBytes32(n, p);
|
||||
if (sp < np) {
|
||||
// s < n in the upper bits (everything before is equal) → s < n globally: ok
|
||||
break;
|
||||
} else if (sp > np || p == length - 0x20) {
|
||||
// s > n in the upper bits (everything before is equal) → s > n globally: fail
|
||||
// or
|
||||
// s = n and we are looking at the lower bits → s = n globally: fail
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// RSAVP1 https://datatracker.ietf.org/doc/html/rfc8017#section-5.2.2
|
||||
// The previous check guarantees that n > 0. Therefore modExp cannot revert.
|
||||
bytes memory buffer = Math.modExp(s, e, n);
|
||||
|
||||
// Check that buffer is well encoded:
|
||||
// buffer ::= 0x00 | 0x01 | PS | 0x00 | DigestInfo
|
||||
//
|
||||
// With
|
||||
// - PS is padding filled with 0xFF
|
||||
// - DigestInfo ::= SEQUENCE {
|
||||
// digestAlgorithm AlgorithmIdentifier,
|
||||
// [optional algorithm parameters] -- not currently supported
|
||||
// digest OCTET STRING
|
||||
// }
|
||||
|
||||
// Get AlgorithmIdentifier from the DigestInfo, and set the config accordingly
|
||||
// - params: includes 00 + first part of DigestInfo
|
||||
// - mask: filter to check the params
|
||||
// - offset: length of the suffix (including digest)
|
||||
bytes32 params; // 0x00 | DigestInfo
|
||||
bytes32 mask;
|
||||
uint256 offset;
|
||||
|
||||
// Digest is expected at the end of the buffer. Therefore if NULL param is present,
|
||||
// it should be at 32 (digest) + 2 bytes from the end. To those 34 bytes, we add the
|
||||
// OID (9 bytes) and its length (2 bytes) to get the position of the DigestInfo sequence,
|
||||
// which is expected to have a length of 0x31 when the NULL param is present or 0x2f if not.
|
||||
if (bytes1(_unsafeReadBytes32(buffer, length - 0x32)) == 0x31) {
|
||||
offset = 0x34;
|
||||
// 00 (1 byte) | SEQUENCE length (0x31) = 3031 (2 bytes) | SEQUENCE length (0x0d) = 300d (2 bytes) | OBJECT_IDENTIFIER length (0x09) = 0609 (2 bytes)
|
||||
// SHA256 OID = 608648016503040201 (9 bytes) | NULL = 0500 (2 bytes) (explicit) | OCTET_STRING length (0x20) = 0420 (2 bytes)
|
||||
params = 0x003031300d060960864801650304020105000420000000000000000000000000;
|
||||
mask = 0xffffffffffffffffffffffffffffffffffffffff000000000000000000000000; // (20 bytes)
|
||||
} else if (bytes1(_unsafeReadBytes32(buffer, length - 0x30)) == 0x2F) {
|
||||
offset = 0x32;
|
||||
// 00 (1 byte) | SEQUENCE length (0x2f) = 302f (2 bytes) | SEQUENCE length (0x0b) = 300b (2 bytes) | OBJECT_IDENTIFIER length (0x09) = 0609 (2 bytes)
|
||||
// SHA256 OID = 608648016503040201 (9 bytes) | NULL = <implicit> | OCTET_STRING length (0x20) = 0420 (2 bytes)
|
||||
params = 0x00302f300b060960864801650304020104200000000000000000000000000000;
|
||||
mask = 0xffffffffffffffffffffffffffffffffffff0000000000000000000000000000; // (18 bytes)
|
||||
} else {
|
||||
// unknown
|
||||
return false;
|
||||
}
|
||||
|
||||
// Length is at least 0x100 and offset is at most 0x34, so this is safe. There is always some padding.
|
||||
uint256 paddingEnd = length - offset;
|
||||
|
||||
// The padding has variable (arbitrary) length, so we check it byte per byte in a loop.
|
||||
// This is required to ensure non-malleability. Not checking would allow an attacker to
|
||||
// use the padding to manipulate the message in order to create a valid signature out of
|
||||
// multiple valid signatures.
|
||||
for (uint256 i = 2; i < paddingEnd; ++i) {
|
||||
if (bytes1(_unsafeReadBytes32(buffer, i)) != 0xFF) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// All the other parameters are small enough to fit in a bytes32, so we can check them directly.
|
||||
return
|
||||
bytes2(0x0001) == bytes2(_unsafeReadBytes32(buffer, 0x00)) && // 00 | 01
|
||||
// PS was checked in the loop
|
||||
params == _unsafeReadBytes32(buffer, paddingEnd) & mask && // DigestInfo
|
||||
// Optional parameters are not checked
|
||||
digest == _unsafeReadBytes32(buffer, length - 0x20); // Digest
|
||||
}
|
||||
}
|
||||
|
||||
/// @dev Reads a bytes32 from a bytes array without bounds checking.
|
||||
function _unsafeReadBytes32(bytes memory array, uint256 offset) private pure returns (bytes32 result) {
|
||||
// Memory safeness is guaranteed as long as the provided `array` is a Solidity-allocated bytes array
|
||||
// and `offset` is within bounds. This is the case for all calls to this private function from {pkcs1Sha256}.
|
||||
assembly ("memory-safe") {
|
||||
result := mload(add(add(array, 0x20), offset))
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user