Как я могу проверить подпись secp256r1, используя Solidity

Извините, если вы найдете эти вопросы простыми, но я новичок в шифровании. Насколько я знаю, в Solidity есть ecrecoverфункция для этой цели, но она использует secp256k1сигнатуру. который я намерен использовать secp256r1. Я использовал следующие шаги в этой сути , чтобы получитьr,s, an v values.

Затем я применил все проверки secp256r1 из WIKIpedia следующим образом.

 1. getting r,s, and v values. 
 2. verify that r, s are integers in [1,n-1].
 3. calculate the hashing of the message.
 4. calculate w = s^-1 mod n
 5. calculate the curve point (x1,y1) = u1 x G + u2 x Q

Подсказка: ecadd добавляет точечную функцию, которую я написал. ecmul — функция умножения, isPoint: проверяет, находится ли точка на кривой или нет.

Мои вопросы,

1- правильно ли я написал пять шагов уравнения; Я не из 4-й и 5-й ступеней. Вы можете проверить код функции проверки для получения дополнительной информации.

2- если я хочу проверить проверку. Я должен отправить сообщение и подпись. мне нужно вернуть больше, чем True/False для проверки.

// testing signature function
// getting r, s, and v values from signature.
// steps would be as follows
// 1. getting r,s, and v values.
function ectest(bytes32 hash, bytes sig) returns (bool) {
    bytes32 r;
    bytes32 s;
    uint8 v;

    if (sig.length != 65)
      return (false, 0);

    // The signature format is a compact form of:
    //   {bytes32 r}{bytes32 s}{uint8 v}
    // Compact means, uint8 is not padded to 32 bytes.
assembly {
    r := mload(add(sig, 32))
    s := mload(add(sig, 64))

    // Here we are loading the last 32 bytes. We exploit the fact that
    // 'mload' will pad with zeroes if we overread.
    // There is no 'mload8' to do this, but that would be nicer.
    v := byte(0, mload(add(sig, 96)))

    // Alternative solution:
    // 'byte' is not working due to the Solidity parser, so lets
    // use the second best option, 'and'
    // v := and(mload(add(sig, 65)), 255)
}

// albeit non-transactional signatures are not specified by the YP, one would expect it
// to match the YP range of [27, 28]

if (v < 27)
  v += 27;

if (v != 27 && v != 28)
    return (false, 0);

// 2. verify that r, s are integers in [1,n-1] using isPoint function
if(isPoint(r,s) == false)
{
  return (false, 0);
}


//3. calculate the hashing of the message
e = sha3(msg);

//4. let v be the leftmost bits of msg
// calculate above in the assembly code
// v



      //5. calculate w = s^-1 mod n
      w  = invmod(s,n);
      // u1 = v * w mod n
      u1 = (v * w) % n ;
      // u2 = r * w mod n
      u2 = (r * w) % n;

      //6. calculate the curve point (x1,y1) = u1 x G + u2 x Q
      (x3,y3)=  ecmul(gx,gy,u1);
      (x4,y4)= ecmul(gx,gy,u2);

      (x1,y1) = ecadd(x3,y3,x4,y4);
      //7. check the validation
      if (r == x1)
      {
        return (true);
      }
    }// end function

}

Я разочарован тем, что никто не отвечает на его вопрос. Люди предположили, что он спрашивал о secp256k1.
Ах. Извините, прочитав предыдущий комментарий, вижу, что он хочет кривой secp256r1.

Ответы (4)

Это важный вопрос, поскольку весь остальной мир (мобильные устройства, смарт-карты, HSM и т. д.) использует secp256r1.

На http://blog.enuma.io/update/2016/11/01/a-tale-of-two-curves-hardware-signing-for-ethereum.html есть статья.

но, к сожалению, коды, фактически реализующие функциональность, исчезли. Планирую реконструировать это из байт-кода, но это может занять некоторое время...

На https://github.com/tdrerup/elliptic-curve-solidity есть чистая реализация Solidity SECP256R1/P256/PRIME256V1 .

Главный недостаток, вероятно, заключается в том, что проверка неродной подписи в Solidity довольно дорогая. Репозиторий включает в себя несколько трюфельных тестов, которые должны помочь понять форматирование переменных.

Будьте осторожны, когда вы используете функцию подписи web3js, потому что она делает какой-то странный префикс перед подписью.

Я сделал туториал о том, как подписывать и проверять данные с помощью Solidity и web3js .

1) Функция ecrecoverвстроена в Solidity, поэтому вам не нужны все эти шаги.

2) Это действительно зависит от того, что вы делаете с ним. Имейте в виду, что если вы подписываете сообщение (например, eth_personalSign), к подписанному сообщению добавляется префикс сообщения, строка «\x19Ethereum Signed Message:\n», за которой следует длина сообщения.

Использование ecrecoverпоначалу немного сложно, но как только вы освоите его, удивительный мир возможностей окажется у вас под рукой.


Пример контракта Solidity:

contract Foobar {
    function checkSignature(bytes32 digest, uint8 v, bytes32 r, byres32 s) constant returns (address signer) {
        return ecrecover(digest, v, r, s);
    }
}

Пример JavaScript:

var ethers = require('ethers');

var privateKey = "0x0123456789012345678901234567890123456789012345678901234567890123";
var signingKey = new ethers.SigningKey(privateKey);
// SigningKey {
//    privateKey: '0x0123456789012345678901234567890123456789012345678901234567890123',
//    publicKey: '0x026655feed4d214c261e0a6b554395596f1f1476a77d999560e5a8df9b8a1a3515',
//    address: '0x14791697260E4c9A71f18484C9f997B308e59325',
// }

// The id function computes the keccak256 of a utf-8 string
var digest = ethers.utils.id("Hello World);
// '0x592fa743889fc7f92ac2a37bb1f5ba1daf2a5c84741ca0e0061d243a2e6707ba'

var sig = signingKey.signMessage(digest);
// { 
//    recoveryParam: 0,
//    r: '0x79f56f3422dc67f57b2aeeb0b20295a99ec90420b203177f83d419c98beda7fe',
//    s: '0x1a9d05433883bdc7e6d882740f4ea7921ef458a61b2cfe6197c2bb1bc47236fd'
// }

var contract = new ethers.Contract( ... )

// The v needs 27 added to it; this is legacy from a Bitcoin standard
var req = contract.checkSig(digest, sig.recoveryParam + 27, sig.r, sig.s);

// Call the Solidity function
req.then(function(signer) {
    console.log(signer);
    // "0x14791697260E4c9A71f18484C9f997B308e59325"
});

Пример реального мира:

Вот краткий реестр стикеров, который я создал для рекламной кампании стикеров Firefly. Каждая наклейка генерируется процедурно и уникальна, а на обратной стороне есть закрытый ключ, который можно использовать для выкупа наклейки. Но на закрытом ключе нет средств. Вместо этого пользователь использует свои собственные средства для оплаты газа, чтобы отправить сообщение, подписанное закрытым ключом стикера. Контракт подтверждает, что наклейка действительна, используя ecrecoverи просматривая наклейку в дереве меркле, после чего наклейка передается пользователю.

https://etherscan.io/address/0xb90e64082d00437e65a76d4c8187596bc213480a#code

ecrecoverожидает Ed25519подписи я верю