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

Address from a private key #14

Closed
rumkin opened this issue Mar 2, 2020 · 3 comments
Closed

Address from a private key #14

rumkin opened this issue Mar 2, 2020 · 3 comments

Comments

@rumkin
Copy link

rumkin commented Mar 2, 2020

Hi, I'm writing an EIP of non-transferable contracts. I'm wondering could you add an example of receiving an address from a private key. I would include references to the organization and the repository in my EIP.

@mariocao
Copy link
Contributor

mariocao commented Mar 18, 2020

Hi @rumkin, thanks for considering our library.

The example/Secp256k1.sol contract was only included as an example as it is not recommended to use cryptographically sensitive information as input parameters. :)

However, generating the address is quite easy and can be computed as follows:

  1. derive public key from the example derivePubKey function
  2. compute hash using keccak256 precompiled function
  3. take only the last 20 bytes

Here you have an snippet of the code:

pragma solidity ^0.6.0;

import "elliptic-curve-solidity/contracts/EllipticCurve.sol";


/**
 * @title Secp256k1 Elliptic Curve
 * @notice Example of particularization of Elliptic Curve for secp256k1 curve
 * @author Witnet Foundation
 */
contract Secp256k1 {

  uint256 public constant GX = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798;
  uint256 public constant GY = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8;
  uint256 public constant AA = 0;
  uint256 public constant BB = 7;
  uint256 public constant PP = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F;

  /// @dev Public Key derivation from private key
  /// @param privKey The private key
  /// @return (qx, qy) The Public Key
  function derivePubKey(uint256 privKey) external pure returns (uint256, uint256) {
    return EllipticCurve.ecMul(
      privKey,
      GX,
      GY,
      AA,
      PP
    );
  }

  function generateAddress(uint256 privKey) external pure returns (address) {
    (uint256 qx, uint256 qy) = EllipticCurve.ecMul(
      privKey,
      GX,
      GY,
      AA,
      PP
    );

    address addr;
    bytes32 hash = keccak256(encodePoint(qx,qy));
    assembly {
        mstore(0, hash)
        addr := mload(0)
    }

    return addr;
  }

  function encodePoint(uint256 _x, uint256 _y) internal pure returns (bytes memory) {
    uint8 prefix = uint8(2 + (_y % 2));

    return abi.encodePacked(prefix, _x);
  }
}

@rumkin
Copy link
Author

rumkin commented Mar 19, 2020

@mariocao Mario, thanks a lot! To be honest to use sensitive information as input on public blockchain is what required for my proposal of proof of single person ownership. I need this to create a private key burning mechanism, so disclosure is required. I know the trade-offs of this and working on solving them. Thanks again.

@mariocao
Copy link
Contributor

You are welcome. Let us know if you need anything else. 😊

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants