What's the best way to transform bytes of a signature into v, r, s in solidity?

Given that solidity does not have any built-in string/bytes manipulation library, I was wondering what the best practice for extracting v, r, s from a signature inside solidity is.

One can encode sig as string `v-r-s` and use `solidity-stringutils` to extract them, but isn't there a better way to do this?

• Out of interest why do you need to do this inside Solidity? Normally you'd pass them into your contract as separate parameters, so you don't need to mess around with them in your Solidity code. – Edmund Edgar Sep 15 '17 at 11:36
• @EdmundEdgar I'm hitting `Stack too deep` error, so trying to keep params # as little as possible and pass them around to other internal funcs. – d9ngle Sep 15 '17 at 12:31
• Ah OK, makes sense. – Edmund Edgar Sep 15 '17 at 19:33

``````bytes sig = ...;
bytes32 r;
bytes32 s;
uint8 v;
assembly {
}
if (v < 27) v += 27;
``````

This works but can't return bytes32, only string.

``````function extractRSV(bytes sig) returns (string, string, string) {
bytes memory r = new bytes(64);
bytes memory s = new bytes(64);
bytes memory v = new bytes(2);

for (uint8 i = 0 ; i < 64 ; ++i) {
r[i] = sig[i];
s[i] = sig[i+64];
}

v[0] = sig[128];
v[1] = sig[129];

return (string(r), string(s), string(v));
}
``````

Here's a helper library:

``````library ECVerify {
function ecrecovery(bytes32 hash, bytes sig) public constant returns (address) {
bytes32 r;
bytes32 s;
uint8 v;

if (sig.length != 65) {
return 0;
}

assembly {
}

if (v < 27) {
v += 27;
}

if (v != 27 && v != 28) {
return 0;
}

return ecrecover(hash, v, r, s);
}

function ecverify(bytes32 hash, bytes sig, address signer) public constant returns (bool) {
return signer == ecrecovery(hash, sig);
}
}
``````

source