Skip to content
This repository has been archived by the owner on Sep 13, 2024. It is now read-only.

I use contract verify signature, but the address is not correct? #63

Closed
wufeiafei opened this issue Apr 18, 2018 · 8 comments
Closed

I use contract verify signature, but the address is not correct? #63

wufeiafei opened this issue Apr 18, 2018 · 8 comments
Labels

Comments

@wufeiafei
Copy link

hi,
I use web3swift method "Web3Signer.signPersonalMessage" make a signature, then I use the contract method "validate", but the result is not correct, the address is different with the signature address.
this is my contract:

pragma solidity ^0.4.17;

contract BBQ {

//验签数据入口函数
function validate(uint8 v,bytes32 r,bytes32 s,uint number) view returns (address,bool){

    string memory message = uint2str(number);
    string memory lengths = uint2str(bytes(message).length);
    string memory prefix = strConcat("\u0019Ethereum Signed Message:\n",lengths);
    bytes32 data = sha3(bytes(prefix),bytes(uint2str(number)));
    bytes32 prefixedHash = sha3(data);
    address endecodedAddress = ecrecover(prefixedHash, v, r, s);

    return (endecodedAddress,msg.sender == endecodedAddress);
}

function uint2str(uint i) internal pure returns (string){
    if (i == 0) return "0";
    uint j = i;
    uint length;
    
    while (j != 0){
        length++;
        j /= 10;
    }
    
    bytes memory bstr = new bytes(length);
    uint k = length - 1;
    
    while (i != 0){
        bstr[k--] = byte(48 + i % 10);
        i /= 10;
    }
    return string(bstr);
}

// 连接两个string
function strConcat(string _a, string _b) internal returns (string){
    bytes memory _ba = bytes(_a);
    bytes memory _bb = bytes(_b);

    string memory abcde = new string(_ba.length + _bb.length);
    bytes memory babcde = bytes(abcde);
    uint k = 0;
    for (uint i = 0; i < _ba.length; i++) babcde[k++] = _ba[i];
    for (i = 0; i < _bb.length; i++) babcde[k++] = _bb[i];

    return string(babcde);
}

}

and this is my swift code:

1524043221014
1524043249556

======
pls, help me check it?

@shamatar
Copy link
Contributor

I’ve pushed a test into “developer” branch, it gives an idea of how to get a signature, get V, R, S from it and test it locally. I’ve also separately tested it with ethereumjs-util and got the same result

@shamatar
Copy link
Contributor

I expect to also deploy a contract on Rinkeby to cross-verify it

@shamatar
Copy link
Contributor

Hello @wufeiafei

I've tested everything, it worked as expected.

Here is a solidity contract for ECRecover

pragma solidity ^0.4.19;

import {Conversion} from "./Conversion.sol";

contract ECRecover {
    using Conversion for uint256;
    bytes constant PersonalMessagePrefixBytes = "\x19Ethereum Signed Message:\n";
  
  constructor() public {
      
  }
  
  function hashPersonalMessage(string _message) public pure returns (bytes32 hash) {
      uint256 length = bytes(_message).length;
      hash = keccak256(PersonalMessagePrefixBytes, length.uintToBytes(), _message);
      return hash;
  }
  
  function recoverSigner(string _message, uint8 v, bytes32 r, bytes32 s) public pure returns (address signer) {
      bytes32 hash = hashPersonalMessage(_message);
      if (v < 27) {
          v = v + 27;
      }
      signer = ecrecover(hash, v, r, s);
      return signer;
  }
}

pragma solidity ^0.4.20;

library Conversion {

    function uintToBytes(uint256 self) internal pure returns (bytes memory s) {
        uint maxlength = 100;
        bytes memory reversed = new bytes(maxlength);
        uint256 i = 0;
        while (self != 0) {
            uint256 remainder = self % 10;
            self = self / 10;
            reversed[i++] = byte(48 + remainder);
        }
        s = new bytes(i);
        for (uint256 j = 0; j < i; j++) {
            s[j] = reversed[i - 1 - j];
        }
        return s;
    }
}

In test you can also find an example of how to properly parse a signature and pass it to the contract in the

func testPersonalSignatureOnContract()

Merged in #66

Sincerely, Alex

@wufeiafei
Copy link
Author

hi, I use method "SECP256K1.unmarshalSignature()", show the error "Use of unresolved identifier 'SECP256K1'".
And I has import import web3swift、BigInt、Result、secp256k1_ios and CryptoSwift。

1524102675998
1524102769146

====
what can I do?

@wufeiafei
Copy link
Author

wufeiafei commented Apr 19, 2018

I test your exapmle, the result is ok。
Then I deploy your solidity contract for ECRecover in my private chain, the result is not ok。 I can not get the same address.

this is my code:
1524127227797
1524127278314

this is logs:
Test Case '-[web3swift_iOS_Tests.web3swiftTests testPersonalSignatureOnContract2]' passed (2.364 seconds).
Test Case '-[web3swift_iOS_Tests.web3swiftTests testPersonalSignatureOnContract3]' started.
sender:
EthereumAddress(_address: "0x0b20a195a259eea6fcc644f272c2111141c76d29", type: web3swift_iOS.EthereumAddress.AddressType.normal)
EthereumAddress(_address: "0x0b20a195a259eea6fcc644f272c2111141c76d29", type: web3swift_iOS.EthereumAddress.AddressType.normal)
3 signRes:
Optional(65 bytes)
V = 1
R = b19f774ad98eaf276d2a52d0a4ac5e09f43cf8a1166fe70583a72d0668abb108
S = 151d43a92967ce6551739579f306a49d9ccf1f9bb76a4aaa44134bfc795b7dd4
Personal hash = a1de988600a42c4b4ab089b619297c17d53cffae5d5120d82d8a92d0bb3b78f2
3 hashPersonalMessage:
.success(["hash": 32 bytes, "0": 32 bytes])
/Users/kevin/Documents/study/web3/web3swift/web3swiftTests/web3swiftTests.swift:2439: error: -[web3swift_iOS_Tests.web3swiftTests testPersonalSignatureOnContract3] : XCTAssertTrue failed -
.success(["0": web3swift_iOS.EthereumAddress(_address: "0x0000000000000000000000000000000000000000", type: web3swift_iOS.EthereumAddress.AddressType.normal), "signer": web3swift_iOS.EthereumAddress(_address: "0x0000000000000000000000000000000000000000", type: web3swift_iOS.EthereumAddress.AddressType.normal)])
/Users/kevin/Documents/study/web3/web3swift/web3swiftTests/web3swiftTests.swift:2451: error: -[web3swift_iOS_Tests.web3swiftTests testPersonalSignatureOnContract3] : XCTAssertTrue failed -
Test Case '-[web3swift_iOS_Tests.web3swiftTests testPersonalSignatureOnContract3]' failed (0.185 seconds).
Test Suite 'web3swiftTests' failed at 2018-04-19 16:32:22.487.
Executed 3 tests, with 2 failures (0 unexpected) in 2.551 (2.558) seconds
Test Suite 'web3swift-iOS_Tests.xctest' failed at 2018-04-19 16:32:22.490.
Executed 3 tests, with 2 failures (0 unexpected) in 2.551 (2.562) seconds
Test Suite 'Selected tests' failed at 2018-04-19 16:32:22.491.
Executed 3 tests, with 2 failures (0 unexpected) in 2.551 (2.566) seconds
Program ended with exit code: 1

@shamatar
Copy link
Contributor

Hello @wufeiafei

I've exposed function unmarshalSignature and marshalSignature as a part of Web3.Utils.

@wufeiafei
Copy link
Author

I test your exapmle, the result is ok。
Then I deploy your solidity contract for ECRecover in my private chain, the result is not ok。 I can not get the same address.

@wufeiafei
Copy link
Author

Thank you very much.
I konw the reseason why the address is different.
the contract signature use hash 2 times, but web3swift hash only one time.
I has add the method "signPersonalMessage2Hash" and "personalECRecover2Hash", and pull requests.

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

No branches or pull requests

3 participants