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
Implement RSA verification #4952
base: master
Are you sure you want to change the base?
Conversation
|
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.
Managed to navigate through RFC 8017 and mostly looks good.
unchecked { | ||
// cache and check length | ||
uint256 length = mod.length; | ||
if (length < 0x40 || length != sig.length) { |
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.
I guess we reject length less than 0x40
because it wouldn't be secure. I wonder if 0x40
was arbitrarily chosen. If so, we need to evaluate it carefully, as far as I remember, RSA's security is p * q
so a 512 bits signature is crackable in reasonable time.
Found this as a reference, but seems like 512 bits (0x40 bytes) signatures are pretty much broken.
https://github.com/tomrittervg/cloud-and-control/blob/master/gnfs-info/factoring-howto.txt
RFC 3447 is from 2003 and was superseded by RFC 8017, though, I couldn't find a recommendation for the mod length. Allegedly, 512 bits security was first broken in 1999, so my estimations say that we might increase this to 0x80
at least.
Needs discussion
if (_unsafeReadBytes1(buffer, length - 50) == 0x31) { | ||
// case: sha256Explicit | ||
offset = 0x34; | ||
params = 0x003031300d060960864801650304020105000420000000000000000000000000; | ||
mask = 0xffffffffffffffffffffffffffffffffffffffff000000000000000000000000; | ||
} else if (_unsafeReadBytes1(buffer, length - 48) == 0x2F) { | ||
// case: sha256Implicit | ||
offset = 0x32; | ||
params = 0x00302f300b060960864801650304020104200000000000000000000000000000; | ||
mask = 0xffffffffffffffffffffffffffffffffffff0000000000000000000000000000; | ||
} else { | ||
// unknown | ||
return false; | ||
} |
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.
From the RFC, Section 9.2 defines the algorithm identifier, but turns out the explicit NULL param is mentioned in Appendix C.
Allowed EMSA-PKCS1-v1_5 digest algorithms.
PKCS1-v1-5DigestAlgorithms ALGORITHM-IDENTIFIER ::= {
{ OID id-md2 PARAMETERS NULL }|
{ OID id-md5 PARAMETERS NULL }|
{ OID id-sha1 PARAMETERS NULL }|
{ OID id-sha224 PARAMETERS NULL }|
{ OID id-sha256 PARAMETERS NULL }|
{ OID id-sha384 PARAMETERS NULL }|
{ OID id-sha512 PARAMETERS NULL }|
{ OID id-sha512-224 PARAMETERS NULL }|
{ OID id-sha512-256 PARAMETERS NULL }
}When id-md2 and id-md5 are used in an AlgorithmIdentifier, the parameters field shall have a value of type NULL. When id-sha1, id-sha224, id-sha256, id-sha384, id-sha512, id-sha512-224, and id-sha512-256 are used in an AlgorithmIdentifier, the parameters (which are optional) SHOULD be omitted, but if present, they SHALL have a value of type NULL. However, implementations MUST accept AlgorithmIdentifier values both without parameters and with NULL parameters.
Pending to verify it, but then the byte difference between 0x31
and 0x2F
should come from the explicit null param (that is 05 00
). I'm just not sure how to encode that section explicitly,
Work in progress. Based on https://github.com/adria0/SolRsaVerify
Tests:
SigVer15_186-3.rsp
from here and automatically run all test examples.For now, only sha256 is supported.
@nobles/hash
provides all the function we need to generate the digest, andSigVer15_186-3.rsp
contains more tests.Do we want to support more?
PR Checklist
npx changeset add
)