-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add secp256k1 + keccak256 to signature verification. #3205
Conversation
…-secp256k1 # Conflicts: # src/Neo/Cryptography/Crypto.cs # src/Neo/SmartContract/ApplicationEngine.Crypto.cs
protected internal readonly static Dictionary<byte, ECCurve> ECCurveSelection = new(){ | ||
{ 0x00, ECCurve.Secp256r1 }, | ||
{ 0x01, ECCurve.Secp256k1 }, | ||
}; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(This may not be the best place to put this dictionary)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why?
Hey @roman-khimov, this feature is required by some exchanges that only support secp256k1 to sign transactions, its hardware restrained and can not be updated. Thus, we need to add support to verify secp256k1 signed transactions. But we only verify it, we dont construct it. |
How come it wasn't a problem for years of Neo existence? This raises so many compatibility questions that I don't even know where to begin. Addresses/wallets/script parsers/NeoFS accounts/NeoX accounts. Likely the issue can be solved with |
New syscall:System.Crypto.CheckSigV2 System.Crypto.CheckMultisigV2 Data Type: InvocationScript: Old format Curve: 0x00 r1, Hash: 0x00 SHA256, Exampe: using ScriptBuilder verificationScriptBuilder = new();
verificationScriptBuilder.EmitRaw([0x01]); // Push curve secp256K1
verificationScriptBuilder.EmitRaw([0x01]); // Push Keccak256 hasher
verificationScriptBuilder.EmitPush(pubKey); // Push pubkey
verificationScriptBuilder.EmitSysCall(ApplicationEngine.System_Crypto_CheckSigV2); Price:SignatureContractCostV2: MultiSignatureContractCostV2: How to check if a verification script is V2: private static ReadOnlySpan<byte> ParseScriptV2(ReadOnlySpan<byte> script, out bool? isV2, out ECCurve? curve, out Hasher? hasher)
{
if (script.Length < 40) throw new FormatException("The verification script is too short.");
isV2 = BinaryPrimitives.ReadUInt32LittleEndian(script[^4..]) == ApplicationEngine.System_Crypto_CheckSigV2 ||
BinaryPrimitives.ReadUInt32LittleEndian(script[^4..]) == ApplicationEngine.System_Crypto_CheckMultisigV2;
curve = ECCurve.Secp256r1;
hasher = Hasher.SHA256;
if (!isV2.Value)
{
return script;
}
curve = script[0] == 0x01 ? ECCurve.Secp256k1 : ECCurve.Secp256r1;
hasher = script[1] == 0x01 ? Hasher.Keccak256 : Hasher.SHA256;
return script[2..];
} |
Note: Still need to add it to the hard fork. |
|
||
public static byte[] Keccak256(this ReadOnlySpan<byte> value) | ||
{ | ||
return Keccak256(value.ToArray()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return Keccak256(value.ToArray()); | |
return Keccak256([.. value]); |
|
||
public static byte[] Keccak256(this Span<byte> value) | ||
{ | ||
return Keccak256(value.ToArray()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return Keccak256(value.ToArray()); | |
return Keccak256([.. value]); |
@@ -415,21 +415,21 @@ public virtual VerifyResult VerifyStateIndependent(ProtocolSettings settings) | |||
UInt160[] hashes = GetScriptHashesForVerifying(null); | |||
for (int i = 0; i < hashes.Length; i++) | |||
{ | |||
if (IsSignatureContract(witnesses[i].VerificationScript.Span)) | |||
if (IsSignatureContract(witnesses[i].VerificationScript.Span, out bool? isV2, out ECCurve? curve, out Hasher? hasher)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dont add ?
nullable
until project is convert to nullable
project.
{ | ||
if (hashes[i] != witnesses[i].ScriptHash) return VerifyResult.Invalid; | ||
var pubkey = witnesses[i].VerificationScript.Span[2..35]; | ||
var pubkey = isV2.Value ? witnesses[i].VerificationScript.Span[4..37] : witnesses[i].VerificationScript.Span[2..35]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
var pubkey = isV2.Value ? witnesses[i].VerificationScript.Span[4..37] : witnesses[i].VerificationScript.Span[2..35]; | |
var pubkey = isV2.Value ? witnesses[i].VerificationScript[4..37] : witnesses[i].VerificationScript[2..35]; |
try | ||
{ | ||
if (!Crypto.VerifySignature(this.GetSignData(settings.Network), witnesses[i].InvocationScript.Span[2..], pubkey, ECCurve.Secp256r1)) | ||
if (!Crypto.VerifySignature(this.GetSignData(settings.Network), witnesses[i].InvocationScript.Span[2..], pubkey, curve, hasher.Value)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (!Crypto.VerifySignature(this.GetSignData(settings.Network), witnesses[i].InvocationScript.Span[2..], pubkey, curve, hasher.Value)) | |
if (!Crypto.VerifySignature(this.GetSignData(settings.Network), witnesses[i].InvocationScript[2..], pubkey, curve, hasher.Value)) |
return VerifyResult.InvalidSignature; | ||
} | ||
catch | ||
{ | ||
return VerifyResult.Invalid; | ||
} | ||
} | ||
else if (IsMultiSigContract(witnesses[i].VerificationScript.Span, out var m, out ECPoint[] points)) | ||
else if (IsMultiSigContract(witnesses[i].VerificationScript.Span, out var m, out ECPoint[] points, out isV2, out curve, out hasher)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
else if (IsMultiSigContract(witnesses[i].VerificationScript.Span, out var m, out ECPoint[] points, out isV2, out curve, out hasher)) | |
else if (IsMultiSigContract(witnesses[i].VerificationScript, out var m, out ECPoint[] points, out isV2, out curve, out hasher)) |
Just to be in sync with Discord: we've discussed it with @roman-khimov and prepared an alternative concept that do not require core protocol modifications and do not require custom verification contract deployment. The solution is rather simple: use custom witness verification script with a call to native CryptoLib's |
Can't they use |
It's possible to use his |
A port of nspcc-dev/neo-go@1e2b438. This commit contains minor protocol extension needed for custom Koblitz-based verification scripts (an alternative to #3205). Replace native CryptoLib's verifyWithECDsa `curve` parameter by `curveHash` parameter which is a enum over supported pairs of named curves and hash functions. Even though this change is a compatible extension of the protocol, it changes the genesis state due to parameter renaming (CryptoLib's manifest is changed). But we're going to resync chain in 3.7 release anyway, so it's not a big deal. Also, we need to check mainnet and testnet compatibility in case if anyone has ever called verifyWithECDsa with 24 or 25 `curve` value. Signed-off-by: Anna Shaleva <[email protected]>
Koblitz-based and Keccak-based transaction witness verification for single signature and multisignature ported from nspcc-dev/neo-go#3425. An alternative to #3205. Signed-off-by: Anna Shaleva <[email protected]>
A port of nspcc-dev/neo-go@1e2b438. This commit contains minor protocol extension needed for custom Koblitz-based verification scripts (an alternative to #3205). Replace native CryptoLib's verifyWithECDsa `curve` parameter by `curveHash` parameter which is a enum over supported pairs of named curves and hash functions. NamedCurve enum mark as deprecated and replaced by NamedCurveHash with compatible behaviour. Even though this change is a compatible extension of the protocol, it changes the genesis state due to parameter renaming (CryptoLib's manifest is changed). But we're going to resync chain in 3.7 release anyway, so it's not a big deal. Also, we need to check mainnet and testnet compatibility in case if anyone has ever called verifyWithECDsa with 24 or 25 `curve` value. Signed-off-by: Anna Shaleva <[email protected]>
Koblitz-based and Keccak-based transaction witness verification for single signature and multisignature ported from nspcc-dev/neo-go#3425. An alternative to #3205. Signed-off-by: Anna Shaleva <[email protected]>
…#3209) * Native: extend CryptoLib's verifyWithECDsa with hasher parameter A port of nspcc-dev/neo-go@1e2b438. This commit contains minor protocol extension needed for custom Koblitz-based verification scripts (an alternative to #3205). Replace native CryptoLib's verifyWithECDsa `curve` parameter by `curveHash` parameter which is a enum over supported pairs of named curves and hash functions. NamedCurve enum mark as deprecated and replaced by NamedCurveHash with compatible behaviour. Even though this change is a compatible extension of the protocol, it changes the genesis state due to parameter renaming (CryptoLib's manifest is changed). But we're going to resync chain in 3.7 release anyway, so it's not a big deal. Also, we need to check mainnet and testnet compatibility in case if anyone has ever called verifyWithECDsa with 24 or 25 `curve` value. Signed-off-by: Anna Shaleva <[email protected]> * SmartContract: add extension to ScriptBuilder for System.Contract.Call Group the set of common operations required to emit System.Contract.Call appcall. Signed-off-by: Anna Shaleva <[email protected]> * Native: add an example of custom Koblitz signature verification Koblitz-based and Keccak-based transaction witness verification for single signature and multisignature ported from nspcc-dev/neo-go#3425. An alternative to #3205. Signed-off-by: Anna Shaleva <[email protected]> * SmartContract: make multisig koblitz easier to parse 1. Make prologue be exactly the same as regular CheckMultisig. 2. But instead of "SYSCALL System.Crypto.CheckMultisig" do INITSLOT and K check. 3. This makes all of the code from INITSLOT below be independent of N/M, so one can parse the script beginning in the same way CheckMultisig is parsed and then just compare the rest of it with some known-good blob. 4. The script becomes a tiny bit larger now, but properties above are too good. Ported from nspcc-dev/neo-go@34ee294. Signed-off-by: Anna Shaleva <[email protected]> * SmartContract: use ABORT in Koblitz multisig Make the script a bit shorter. ABORTMSG would cost a bit more. Ported from nspcc-dev/neo-go@fb16891. Ref. nspcc-dev/neo-go#3425 (comment). Signed-off-by: Anna Shaleva <[email protected]> * SmartContract: reduce callflag scope for Koblitz verification scripts All flag is too wide. A port of nspcc-dev/neo-go@fe292f3. Ref. nspcc-dev/neo-go#3425 (comment). Signed-off-by: Anna Shaleva <[email protected]> * Native: add tests for CryptoLib's verifyWithECDsa No functional changes, just add more unit-tests. Signed-off-by: Anna Shaleva <[email protected]> * Native: update NamedCurveHash values for Keccak256 hasher Use 122 and 123 respectively for secp256k1Keccak256 and secp256r1Keccak256. Signed-off-by: Anna Shaleva <[email protected]> * SmartContract: move EmitAppCallNoArgs to the testing code We're not going to implement custom Koblitz witness generation at the core, and thus, the only user of this API is testing code. Signed-off-by: Anna Shaleva <[email protected]> * Apply suggestions from code review clean ut lines * fix names * Cryptography: cache ECDomainParameters for Secp256r1 and Secp256k1 Signed-off-by: Anna Shaleva <[email protected]> * Update tests/Neo.UnitTests/SmartContract/Native/UT_CryptoLib.cs * Update tests/Neo.UnitTests/SmartContract/Native/UT_CryptoLib.cs * Update tests/Neo.UnitTests/SmartContract/Native/UT_CryptoLib.cs * Update tests/Neo.UnitTests/SmartContract/Native/UT_CryptoLib.cs * Update tests/Neo.UnitTests/SmartContract/Native/UT_CryptoLib.cs * Update tests/Neo.UnitTests/SmartContract/Native/UT_CryptoLib.cs * Update tests/Neo.UnitTests/SmartContract/Native/UT_CryptoLib.cs * Update tests/Neo.UnitTests/SmartContract/Native/UT_CryptoLib.cs * Update tests/Neo.UnitTests/SmartContract/Native/UT_CryptoLib.cs * Update tests/Neo.UnitTests/SmartContract/Native/UT_CryptoLib.cs * Update tests/Neo.UnitTests/SmartContract/Native/UT_CryptoLib.cs * Update tests/Neo.UnitTests/SmartContract/Native/UT_CryptoLib.cs * Update tests/Neo.UnitTests/SmartContract/Native/UT_CryptoLib.cs * Update tests/Neo.UnitTests/SmartContract/Native/UT_CryptoLib.cs * Update tests/Neo.UnitTests/SmartContract/Native/UT_CryptoLib.cs --------- Signed-off-by: Anna Shaleva <[email protected]> Co-authored-by: Shargon <[email protected]> Co-authored-by: Jimmy <[email protected]>
Close because of #3209 |
Description
This pr focus on adding support to secp256k1 signed transactions and hashed with Keccak256.
Fixes # (issue)
Type of change
How Has This Been Tested?
Test Configuration:
Checklist: