For those of you who are also looking for this. Actually it is not exactly what I wanted in the question but it works perfectly for my requirements.
What I do is essentially signing some data, not the transaction, and then retrieving the data from the smart contract, so it is basically the same.
For the geth verify and check signatures, this is the code:
function sign(address, value){
var hash = web3.sha3(value.toString());
var sig = web3.eth.sign(address, hash)
//var result = personal.ecRecover(h, "0x"+sig)
// send to user => value, address, result
return [hash,sig];
}
function rsv_generate(signature){
signature = signature.slice(2);
var r = '0x' + signature.slice(0, 64);
var s = '0x' + signature.slice(64, 128);
var v = web3.toDecimal(parseInt("0x"+signature.slice(128,130))); // must be +27 of not 28 or 27
return [r,s,v]
}
function verify(message, hash, signature, address) {
var hashed_message = web3.sha3(message.toString());
var signer_address = personal.ecRecover(hash,signature);
return (hashed_message == hash) && (signer_address == address);
}
function verify(message, result, address) {
var hash = result[0];
var signature = result[1]
var hashed_message = web3.sha3(message.toString());
var signer_address = personal.ecRecover(hash,signature);
return (hashed_message == hash) && (signer_address == address);
}
Then, in the solidity code, the same check as offline can be done in the following way:
pragma solidity ^0.4.19;
contract chargingContract {
function verify(string message, address p, bytes32 hash, uint8 v, bytes32 r, bytes32 s) pure public returns(bool) {
bytes memory prefix = "\x19Ethereum Signed Message:\n32"; //necessary in Solidity as of 0.4.19
bytes32 prefixedHash = keccak256(prefix, hash);
bytes32 hashedMessage = sha3(message);
return ecrecover(prefixedHash, v, r, s) == p && hashedMessage == hash;
}
}
I'm also not a Rust programmer, so someone will probably have a better answer, but have a look in Parity's keypair.rs
, which itself uses rust-secp256k1
.
Of interest is probably the KeyPair
implementation.
impl KeyPair {
/// Create a pair from secret key
pub fn from_secret(secret: Secret) -> Result<KeyPair, Error> {
let context = &SECP256K1;
let s: key::SecretKey = key::SecretKey::from_slice(context, &secret[..])?;
let pub_key = key::PublicKey::from_secret_key(context, &s)?;
let serialized = pub_key.serialize_vec(context, false);
let mut public = Public::default();
public.copy_from_slice(&serialized[1..65]);
let keypair = KeyPair {
secret: secret,
public: public,
};
Ok(keypair)
}
...
Best Answer
There is a package for this called ethereum-tx-sign on crates.io. It provides a
RawTransaction
structure with asign
method. It doesn't have any dependency on web3 and you can sign the transactions offline.