-
Notifications
You must be signed in to change notification settings - Fork 29
Use utf8 string for private key subject with non-printable characters #710
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
Conversation
nssdb/keys.go
Outdated
| var printableRx = regexp.MustCompile(`^[a-zA-Z0-9 '()+,\-.\\:=?]*$`) | ||
|
|
||
| func isPrintable(s string) bool { | ||
| return printableRx.MatchString(s) | ||
| } |
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.
Is this a limitation of nssdb?
The unicode package has a method for validating whether a run is printable IsPrint(rune). Some more complicated limitations can be done using the In(r rune, ranges ...*RangeTable) function, for example, to limit the runes to be in the Latin RangeTable, or you can also create your own.
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 refers to the asn.1 type of printable strings, which is more restrictive than the unicode IsPrint function. In a certificate where the common name contains only printable characters it's encoded with the asn1 tag for PrintableString. For anything else it gets the asn1 tag for UTF8String. (At least that's how it works for our certificates.)
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.
Looping runes will perform better:
Lines 183 to 213 in 9fd47c3
| // isPrintableString reports whether the given s is a valid ASN.1 PrintableString. | |
| // If asterisk is allowAsterisk then '*' is also allowed, reflecting existing | |
| // practice. If ampersand is allowAmpersand then '&' is allowed as well. | |
| func isPrintableString(s string, asterisk, ampersand bool) bool { | |
| for _, b := range s { | |
| valid := 'a' <= b && b <= 'z' || | |
| 'A' <= b && b <= 'Z' || | |
| '0' <= b && b <= '9' || | |
| '\'' <= b && b <= ')' || | |
| '+' <= b && b <= '/' || | |
| b == ' ' || | |
| b == ':' || | |
| b == '=' || | |
| b == '?' || | |
| // This is technically not allowed in a PrintableString. | |
| // However, x509 certificates with wildcard strings don't | |
| // always use the correct string type so we permit it. | |
| (asterisk && b == '*') || | |
| // This is not technically allowed either. However, not | |
| // only is it relatively common, but there are also a | |
| // handful of CA certificates that contain it. At least | |
| // one of which will not expire until 2027. | |
| (ampersand && b == '&') | |
| if !valid { | |
| return false | |
| } | |
| } | |
| return true | |
| } |
Go ans1 loops around bytes using a similar method, this is for one byte https://github.com/golang/go/blob/f24b299df2896a4e8a80863dbb55a264f4b9bb68/src/encoding/asn1/asn1.go#L422-L444
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.
maraino
left a comment
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.
lgtm
When importing a private key into an NSS database with a certificate, the certificate common name is used as the value of the CKA_SUBJECT attribute on the key object. This fixes the serialization to work when the CN contains characters that aren't valid for the asn1 printable string type.
💔Thank you!