lapo-luchini / asn1js

JavaScript generic ASN.1 parser
ISC License
586 stars 161 forks source link

Incomplete Display of IP Address Values in subjectAltName on ASN.1 Decoder #92

Open microshine opened 6 months ago

microshine commented 6 months ago

Issue Description:

When decoding a certificate on https://lapo.it/asn1js, the values for some IP addresses in the subjectAltName field are not displayed correctly. The output shows that the value consists of, for example, 4 bytes, but the hexadecimal representation is missing.

Steps to Reproduce:

  1. Open https://lapo.it/asn1js.
  2. Input the provided certificate data (see below) into the decoder.
  3. Observe the subjectAltName field in the decoded output.

Expected Behavior:

The subjectAltName field should display the full hexadecimal representation of IP addresses.

Actual Behavior:

The subjectAltName field indicates that some IP address values consist of 4 bytes, but the hexadecimal representation is not shown.

Certificate Data:

MIIGyDCCBk6gAwIBAgIQDQsh8YVJ+5rl2I/Z0i4MlzAKBggqhkjOPQQDAzBWMQswCQYDVQQGEwJVUzEV
MBMGA1UEChMMRGlnaUNlcnQgSW5jMTAwLgYDVQQDEydEaWdpQ2VydCBUTFMgSHlicmlkIEVDQyBTSEEz
ODQgMjAyMCBDQTEwHhcNMjMwNzMxMDAwMDAwWhcNMjQwODA2MjM1OTU5WjBbMQswCQYDVQQGEwJVUzET
MBEGA1UECBMKQ2FsaWZvcm5pYTERMA8GA1UEBxMIQmVya2VsZXkxDjAMBgNVBAoTBVF1YWQ5MRQwEgYD
VQQDDAsqLnF1YWQ5Lm5ldDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABH2L1x0DhQ0YJbM0HCmhJ9Ss
ASVIiqDx6gK52FEsCGqsclbs+j2moJ9JCVWOrP65cxdcAvt4zCSRlG9DI4kOHWajggT3MIIE8zAfBgNV
HSMEGDAWgBQKvAgpF4ylOW16Ds4zxy6z7fvDejAdBgNVHQ4EFgQUf6kSpdfGi0gCxz0qRW5AHkBg9Jcw
ggGNBgNVHREEggGEMIIBgIILKi5xdWFkOS5uZXSCCXF1YWQ5Lm5ldIcECQkJCYcECQkJCocECQkJC4cE
CQkJDIcECQkJDYcECQkJDocECQkJD4cElXBwCYcElXBwCocElXBwC4cElXBwDIcElXBwDYcElXBwDocE
lXBwD4cElXBwcIcQJiAA/gAAAAAAAAAAAAAACYcQJiAA/gAAAAAAAAAAAAAAEIcQJiAA/gAAAAAAAAAA
AAAAEYcQJiAA/gAAAAAAAAAAAAAAEocQJiAA/gAAAAAAAAAAAAAAE4cQJiAA/gAAAAAAAAAAAAAAFIcQ
JiAA/gAAAAAAAAAAAAAAFYcQJiAA/gAAAAAAAAAAAAAA/ocQJiAA/gAAAAAAAAAAAP4ACYcQJiAA/gAA
AAAAAAAAAP4AEIcQJiAA/gAAAAAAAAAAAP4AEYcQJiAA/gAAAAAAAAAAAP4AEocQJiAA/gAAAAAAAAAA
AP4AE4cQJiAA/gAAAAAAAAAAAP4AFIcQJiAA/gAAAAAAAAAAAP4AFTAOBgNVHQ8BAf8EBAMCB4AwHQYD
VR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMIGbBgNVHR8EgZMwgZAwRqBEoEKGQGh0dHA6Ly9jcmwz
LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRMU0h5YnJpZEVDQ1NIQTM4NDIwMjBDQTEtMS5jcmwwRqBEoEKG
QGh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRMU0h5YnJpZEVDQ1NIQTM4NDIwMjBDQTEt
MS5jcmwwPgYDVR0gBDcwNTAzBgZngQwBAgIwKTAnBggrBgEFBQcCARYbaHR0cDovL3d3dy5kaWdpY2Vy
dC5jb20vQ1BTMIGFBggrBgEFBQcBAQR5MHcwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0
LmNvbTBPBggrBgEFBQcwAoZDaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VExTSHli
cmlkRUNDU0hBMzg0MjAyMENBMS0xLmNydDAJBgNVHRMEAjAAMIIBfgYKKwYBBAHWeQIEAgSCAW4EggFq
AWgAdgDuzdBk1dsazsVct520zROiModGfLzs3sNRSFlGcR+1mwAAAYmtrLxjAAAEAwBHMEUCIQCAWtmg
TRnZsqjxZ7jdiDq0EEfxBB4kMj7oaZPv+URihQIgUJxBXliHw3ic/24+0NilFj/WfEcV1kNRARUhXS6x
n08AdwBIsONr2qZHNA/lagL6nTDrHFIBy1bdLIHZu7+rOdiEcwAAAYmtrLxLAAAEAwBIMEYCIQClQbGk
sPNEGkRsO930WOdpYDBhFWVD44nw9ks9uyawJAIhAPypE9SPFDDkOgrOw+K++guz486lzdjaAfVzdyO6
sw80AHUA2ra/az+1tiKfm8K7XGvocJFxbLtRhIU0vaQ9MEjX+6sAAAGJray8FwAABAMARjBEAiBMmvof
eflmsV3JoyFVid5GiJaPHkH9fDWkS93eP9fgEQIgfkTwCbSFNKnF47riYP4MJow7haBO+pFwRW5WAEC1
AQQwCgYIKoZIzj0EAwMDaAAwZQIwOOsRrmNqg61CQTVH/6I6W1ZKb+5efJZpgZLVhCirpay7lyiuNyC1
QkF6jfTAh+nGAjEAoRSNqC4pY/1GUJ3ygEjSOkUKlFnpXSxYIxJz9yJ43z05faF/uL+mrpAV9GXi2cpt

ASN.1 Decoded Output Snippet:

SEQUENCE @419+397 (constructed): (2 elem)
  OBJECT_IDENTIFIER @423+3: 2.5.29.17|subjectAltName|X.509 extension
  OCTET_STRING @428+388 (encapsulates): (388 byte)|30820180820B2A2E71756164392E6E6574820971756164392E6E657487040909090987040909090A87040909090B87040909090C87040909090D87040909090E87040909090F87049570700987049570700A87049570700B87049570700C87049570700D87049570700E87049570700F8704957070708710262000FE0000000000000000000000098710262000FE0000000000000000000000108710262000FE0000000000000000000000118710262000FE0000000000000000000000128710262000FE0000000000000000000000138710262000FE0000000000000000000000148710262000FE0000000000000000000000158710262000FE0000000000000000000000FE8710262000FE000000000000000000FE00098710262000FE000000000000000000FE00108710262000FE000000000000000000FE00118710262000FE000000000000000000FE00128710262000FE000000000000000000FE00138710262000FE000000000000000000FE00148710262000FE000000000000000000FE0015
    SEQUENCE @432+384 (constructed): (32 elem)

      [2] @436+11: (11 byte)|*.quad9.net
      [2] @449+9: (9 byte)|quad9.net
      [7] @460+4: (4 byte)|             
      [7] @466+4: (4 byte)|         |
      [7] @472+4: (4 byte)|0909090B
      [7] @478+4: (4 byte)|0909090C
      [7] @484+4: (4 byte)|         
      [7] @490+4: (4 byte)|0909090E
      [7] @496+4: (4 byte)|0909090F
      [7] @502+4: (4 byte)|95707009
      [7] @508+4: (4 byte)|9570700A
      [7] @514+4: (4 byte)|9570700B
      [7] @520+4: (4 byte)|9570700C
      [7] @526+4: (4 byte)|9570700D
      [7] @532+4: (4 byte)|9570700E
      [7] @538+4: (4 byte)|9570700F
      [7] @544+4: (4 byte)|95707070
      [7] @550+16: (16 byte)|262000FE000000000000000000000009
      [7] @568+16: (16 byte)|262000FE000000000000000000000010
      [7] @586+16: (16 byte)|262000FE000000000000000000000011
      [7] @604+16: (16 byte)|262000FE000000000000000000000012
      [7] @622+16: (16 byte)|262000FE000000000000000000000013
      [7] @640+16: (16 byte)|262000FE000000000000000000000014
      [7] @658+16: (16 byte)|262000FE000000000000000000000015
      [7] @676+16: (16 byte)|262000FE0000000000000000000000FE
      [7] @694+16: (16 byte)|262000FE000000000000000000FE0009
      [7] @712+16: (16 byte)|262000FE000000000000000000FE0010
      [7] @730+16: (16 byte)|262000FE000000000000000000FE0011
      [7] @748+16: (16 byte)|262000FE000000000000000000FE0012
      [7] @766+16: (16 byte)|262000FE000000000000000000FE0013
      [7] @784+16: (16 byte)|262000FE000000000000000000FE0014
      [7] @802+16: (16 byte)|262000FE000000000000000000FE0015
lapo-luchini commented 2 months ago

Reason is here:

function checkPrintable(s) {
    let i, v;
    for (i = 0; i < s.length; ++i) {
        v = s.charCodeAt(i);
        if (v < 32 && v != 9 && v != 10 && v != 13) // [\t\r\n] are (kinda) printable
            throw new Error('Unprintable character at index ' + i + ' (code ' + s.str.charCodeAt(i) + ')');
    }
}

The "missing" values are interpreted as printable, because they are respectively "\t\t\t\t", "\t\t\t\n", and "\t\t\t\r" and are thus printed as string (which produces nothing visible).