Получить открытый ключ из подписи в смарт-контракте (примечание, открытый ключ, а не адрес)

Существуют ли библиотеки для получения открытого ключа из подписи в смарт-контракте? Метод ecrecover возвращает адрес, а не открытый ключ, и для выполнения вычислений, требующих получения открытого ключа из подписи, где открытый ключ неизвестен и не передается в контракт другими способами, в то время как подпись известна, было бы хорошо иметь библиотеку, которая получает открытый ключ из подписи.

Частичные библиотеки также были бы полезны здесь.

Ответы (3)

Есть библиотека https://github.com/jbaylina/ecsol , которая реализует некоторые операции над эллиптическими кривыми в солидности.

Я не пробовал, но, похоже, этого достаточно для восстановления открытого ключа. Но я не уверен, что лимит газа позволит такую ​​операцию.

В любом случае задача кажется интересной, но она эквивалентна получению прообраза от keccak.

В Solidity нет встроенного способа сделать это, и я не верю, что существует библиотека для этого. Из любопытства, по какой причине вам нужно получить открытый ключ вместо адреса?

третья версия этой награды, etherscan.io/address/… , где симметричный ключ передается в контракт вместо открытого ключа, а открытый ключ (используемый для решения другого шифра) получается из подписи идентификатора учетной записи.
схема подписи с использованием одноразовых ключей, называемая «тейхос», от греческого «укрепление», она скрывает асимметричную криптографию за невзламываемым симметричным шифром (поддается взлому только путем перебора всех возможных комбинаций)

доступна новая библиотека для восстановления открытого ключа из подписанного сообщения ECDSA https://github.com/0xcyphered/secp256k1-solidity

Пример:

//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;
import "@0xcyphered/secp256k1-solidity/contracts/SECP256K1.sol";
contract Example {
    function recoverPersonalSignPublicKey(
        bytes32 message,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public pure returns (bytes memory) {
        string memory header = '\x19Ethereum Signed Message:\n32';
        bytes32 _message = keccak256(abi.encodePacked(header, message));
        (uint256 x, uint256 y) = SECP256K1.recover(uint256(_message), v - 27, uint256(r), uint256(s));
        return abi.encodePacked(x, y);
    }
}