# Public Key

Recall that an address is the last 20 bytes of the keccak-256 hash of the address’s public key.

To complete this challenge, find the public key for the owner's account.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.11;

contract PublicKey {
    bool public isComplete;
    address public owner;

    constructor(address _owner) {
        owner = _owner;
    }

    function authenticate(bytes memory publicKey) public {
        // Compute the publicKey's keccak256 hash.
        uint256 publicKeyHash = uint256(keccak256(publicKey));
        // Check the lower 20 bytes of the hash.
        require(address(uint160(publicKeyHash)) == owner, "public key does not match");
        isComplete = true;
    }
}

TIP

On this web page, we have loaded the ethers (opens new window) library.

The ethers library has a method called ethers.utils.recoverPublicKey (opens new window) which takes a digest, signature.

The signature object should contain:

{
    r: "0xdead...",
    s: "0xbeef...",
    v: "0x1"
}

and the digest should be a keccak256 digest signed by the private-key of the public-key we want to recover.

  • How can we get a digest signed by the owner and a corresponding signature?

    Hint:

    DETAILS

    In the geth console, you can get a full transaction with its signature with:

    eth.getRawTransaction("0x...")
    
    > "0x02..."
    

    And in ethers, you can get just the RLP-encoded data of a transaction before signing with:

    tx = ethers.utils.parseTransaction("0x02...")
    ethers.utils.serializeTransaction(tx)
    
    > "0x02f89082053981fb847735940084..." 
    

    Once you have a public key, you can verify what address it resolves to with:

    ethers.utils.computeAddress("...PUBLIC_KEY")
    
    > "0x015aA9fC32E280A70B639ECdC6203B917d9bfCdf"