4

I'm trying to do something that in theory is very simple: I want to pass a string like "hello" to a function and then compute the sha3/keccak256 hash. I think the problem is that if the parameter is a bytes32 (as it is now), the hash function will produce a different output.

How can I get the same hashes with these two methods inside a smart contract? In practice, how to get a return true in the following code?

function someFunction(bytes32 _string) returns(bool){
    bool result = false;
    bytes32 hashparameter = sha3(_string);
    bytes32 hashstring = sha3("hello");
    if(hashstring == hashparameter) {
        result = true;
    }

    return result;

}

How can I truncate the passed bytes32 so that it consider only the first 5 bytes for the sha3?

Thanks for your time, I hope you have the solution. If I'll find something, I'll update the question.

eth
  • 85,679
  • 53
  • 285
  • 406
gatb27
  • 350
  • 3
  • 13

3 Answers3

4

try this snipet

function bytes32ToString(bytes32 x) constant returns (string) {
    bytes memory bytesString = new bytes(32);
    uint charCount = 0;
    for (uint j = 0; j < 32; j++) {
        byte char = byte(bytes32(uint(x) * 2 ** (8 * j)));
        if (char != 0) {
            bytesString[charCount] = char;
            charCount++;
        }
    }
    bytes memory bytesStringTrimmed = new bytes(charCount);
    for (j = 0; j < charCount; j++) {
        bytesStringTrimmed[j] = bytesString[j];
    }
    return string(bytesStringTrimmed);
}

 function someFunction(bytes32 _string) returns(bool){
    bool result = false;
    bytes32 hashparameter = sha3(bytes32ToString(_string));
    bytes32 hashstring = sha3("hello");
    if(hashstring == hashparameter) {
        result = true;
    }

    return result;

}

the first function converts bytes32 to string then passes the result to hashing function. I've tried it gives true for "hello".

Badr Bellaj
  • 18,780
  • 4
  • 58
  • 75
  • thank you very much! It's exactly what I was trying to write but I wasn't able to figure out 5th line of your snippet :) – gatb27 Jan 09 '17 at 20:28
0

How can I truncate the passed bytes32 so that it consider only the first 5 bytes for the sha3?

To truncate bytes32 to the first 5 bytes, cast it to bytes5:

bytes5 b5 = bytes5(bytes32value);

In the question contract, use:

keccak256(bytes5(_string));


The question isn't passing a string to keccak256/sha3, it's passing in bytes32. One could use a function to convert the bytes32 to string but it may turn out to not be needed and just use unnecessary gas.

For example, here are 3 options that are much cheaper for making someFunction return true. Choose 1 and replace the matching line in the problem contract:

  • function someFunction(string _string) returns(bool){
    Make the input be a string :)

  • bytes32 hashparameter = keccak256(bytes5(_string)); Make the length match the length of hello.

  • bytes32 hashstring = keccak256("hello\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"); Pad the string to 32 bytes.

But this question sounds like an XY problem:

The XY problem is asking about your attempted solution rather than your actual problem.

That is, you are trying to solve problem X, and you think solution Y would work, but instead of asking about X when you run into trouble, you ask about Y.

For example, where does the hardcoded "hello" come from or get stored in the contract? Wouldn't it also be a bytes32? If it isn't, then padding it to 32 bytes would be much cheaper than converting each bytes32 input to a string.

eth
  • 85,679
  • 53
  • 285
  • 406
  • Thank @eth for the answer. This function is just an example to explain I needed a conversion from bytes32 to string, without the knowledge about how long is the string saved in a bytes32. So the "hello" is just an example to the conversion. I can actually use the string type for the function parameters, but in a specific case I need a conversion and so the first answer by badr bellaj was the one I was looking for :) – gatb27 Jan 25 '17 at 15:12
  • 1
    @gatb27 Thanks, so your actual problem was "conversion from bytes32 to string" which is basically the linked answer :) – eth Jan 25 '17 at 21:59
0
// Copyright 2014 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.

package crypto

import (
    "crypto/ecdsa"
    "crypto/elliptic"
    "crypto/rand"
    "encoding/hex"
    "errors"
    "io"
    "io/ioutil"
    "math/big"
    "os"

    "github.com/ethereum/go-ethereum/common"
    "github.com/ethereum/go-ethereum/crypto/sha3"
    "github.com/ethereum/go-ethereum/rlp"
)

var (
    secp256k1_N, _  = new(big.Int).SetString("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", 16)
    secp256k1_halfN = new(big.Int).Div(secp256k1_N, big.NewInt(2))
)

// Keccak256 calculates and returns the Keccak256 hash of the input data.
func Keccak256(data ...[]byte) []byte {
    d := sha3.NewKeccak256()
    for _, b := range data {
        d.Write(b)
    }
    return d.Sum(nil)
}

// Keccak256Hash calculates and returns the Keccak256 hash of the input data,
// converting it to an internal Hash data structure.
func Keccak256Hash(data ...[]byte) (h common.Hash) {
    d := sha3.NewKeccak256()
    for _, b := range data {
        d.Write(b)
    }
    d.Sum(h[:0])
    return h
}

// Keccak512 calculates and returns the Keccak512 hash of the input data.
func Keccak512(data ...[]byte) []byte {
    d := sha3.NewKeccak512()
    for _, b := range data {
        d.Write(b)
    }
    return d.Sum(nil)
}
Ajoy Bhatia
  • 1,446
  • 15
  • 31