I am wondering how the precompiled contract at address 5 (introduced by EIP-198) can actually be used to do RSA signature verification in Solidity, i.e., how it can be called by another contract (implemented in Solidity) with big integers (larger than 32 byte), e.g., a 4096-bit RSA modulus.

I am aware of the code provided in https://ethereum.stackexchange.com/a/71590. However, the solution focuses on modular exponentiation in which each component (base, exponent, modulus) can be represented with a variable of type uint256. With the RSA modulus typically being of size 1,024 or 2,048 or 4,096 (bits), this solution does not seem to be sufficient to do RSA signature verification. Hence, I am wondering how the solution can be extended to send and receive big integers (represented as bytes) to the precompiled contract. (Note: As RSA verification in practice usually uses an exponent of 3 or 65537, the exponent does not need to be of type bytes)

I would imagine a function for modular exponentation with a 4,096-bit RSA modulus to look (more or less) like this:

function modExp(bytes memory _b, uint _e, bytes memory _m) public returns (bytes memory result) {

     assembly {
        // Free memory pointer
        let pointer := mload(0x40)

        // Define length of base, exponent and modulus. Exponent = 32 bytes (0x20), base and modulus = 4096 bit (0x1000)
        mstore(pointer, 0x1000)
        mstore(add(pointer, 0x20), 0x20)
        mstore(add(pointer, 0x40), 0x1000)

        // Define variables base, exponent and modulus
        mstore(add(pointer, 0x60), _b)
        mstore(add(pointer, 0x1060), _e) //position increments by 0x1000 as _b is of size 0x1000
        mstore(add(pointer, 0x1080), _m) //position increments by 0x20 as _e is of size 0x20

        // Store the result
        let value := mload(0x2080) //position increments by 0x1000 as _m is of size 0x1000

        // Call the precompiled contract 0x05 = bigModExp
        if iszero(call(not(0), 0x05, 0, pointer, 0xc0, value, 0x20)) {
            revert(0, 0)

        result := mload(value)


  • mstore copies just 256 bits, if _b is longer you have to iterate over the memory pointer.
    – Ismael
    Commented Aug 16, 2022 at 4:09

1 Answer 1


you can use the library implementation here to do what you want, it also has RSA signature verification examples:


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.