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

[M-04] Incomplete Bitcoin-Style Address Generation in publicKeyToDMDAddress Function #51

Open
softstackio opened this issue Sep 9, 2024 · 1 comment

Comments

@softstackio
Copy link

Description:
The publicKeyToDMDAddress function in the ClaimContract attempts to generate a Bitcoin-style address from ECDSA public key coordinates. However, the implementation is incomplete as it omits the crucial step of Base58Check encoding, which is standard for Bitcoin addresses. Instead of returning a properly formatted Bitcoin address string, the function returns a raw 20-byte value.

Impact:

  1. Incompatibility: The generated addresses are not compatible with standard Bitcoin address formats, potentially causing issues with integration into Bitcoin-compatible systems or wallets.
  2. Misinterpretation: Users or external systems expecting a standard Bitcoin address format may misinterpret or mishandle the raw byte output.
  3. Additional Processing Required: Any system using this function would need to implement Base58Check encoding separately, increasing the risk of inconsistencies or errors.
  4. Potential Loss of Funds: If these addresses are used directly without proper encoding, it could lead to the loss of funds or inability to claim tokens correctly.

The current implementation only performs part of the Bitcoin address generation process:

  1. It compresses the public key (though this step is also implemented incorrectly).
  2. It applies SHA-256 and RIPEMD-160 hashing.
  3. It omits the version byte, checksum calculation, and Base58Check encoding.
function publicKeyToDMDAddress(
   bytes32 _publicKeyX,
   bytes32 _publicKeyY
) public pure returns (bytes20 rawBtcAddress) {
   return
       ripemd160(
           abi.encodePacked(
               sha256(
                   abi.encodePacked((uint256(_publicKeyY) & 1) == 0 ? 0x02
: 0x03, _publicKeyX)
               )
) );
}

This implementation returns a raw RIPEMD-160 hash instead of a properly formatted Bitcoin address.

Proof of Concept:

  1. Generate a valid ECDSA key pair.
  2. Call publicKeyToDMDAddress with the public key coordinates.
  3. The resulting 20-byte output will not be a valid Bitcoin address and cannot be used
    directly in Bitcoin-compatible systems.

Recommendation:

Implement the full Bitcoin address generation process, including Base58Check encoding:

  1. Properly compress the public key.
  2. Apply SHA-256 hashing to the compressed public key.
  3. Apply RIPEMD-160 hashing to the result of step 2.
  4. Add a version byte (0x00 for mainnet Bitcoin addresses).
  5. Calculate a 4-byte checksum (double SHA-256 of the result from step 4).
  6. Append the checksum to the result from step 4.
  7. Encode the result using Base58Check encoding.
function publicKeyToDMDAddress(bytes32 _publicKeyX, bytes32 _publicKeyY)
public pure returns (string memory) {
   bytes memory compressedPubKey = compressPublicKey(_publicKeyX,
_publicKeyY);
   bytes20 pubKeyHash =
ripemd160(abi.encodePacked(sha256(compressedPubKey)));
   bytes21 versionedPayload = abi.encodePacked(byte(0x00), pubKeyHash);
   bytes32 checksum = sha256(abi.encodePacked(sha256(versionedPayload)));
   bytes25 addressBytes = abi.encodePacked(versionedPayload,
checksum[0:4]);
   return toBase58Check(addressBytes);
}

Note: This corrected implementation requires additional helper functions like compressPublicKey and toBase58Check, which should be implemented separately.

@softstackio
Copy link
Author

We have been successfully generating our own signatures

Generating Signature And Demonstrating its Outcome
docker exec musing_brattain diamond-cli getnewaddress > dLXfUaRQD8MLCjBWjm3vcYKzivDrbFRqbS

docker exec musing_brattain diamond-cli signmessage "dLXfUaRQD8MLCjBWjm3vcYKzivDrbFRqbS" "claim to: 0x05098A2Cc5b414540ed13e33cbE5aC147805Bc63"

H5hd7Ssnwk4Dhdk6xuvcP1GD5UV+lzTUaaYMpdru0XzGVxlaZRZb7oMJgybda6skV6S Ij6dH4pgDQo5gt3c+u3w=

Calculated
X: 0xc96cfd2d2e0005be1b7713eb1e412d758037c451be2dd9a31e58ba69b3c77030 Y: 0x76b5258bcf23cd8f000fc3c2fa8a8acfea13654a75f31388e79ea9665f062f0c
r: 0xb13d7c78c5b3c4ac3161112145cfbe551dd80f2da3e93c28a48bc0a3400795ac s: 0xc2d38e34226a98099b140cda769f4968b886d30783394c3e505fc0a217701339 v: 28

as a side note

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

1 participant