Skip to content

Encode Netscape IA5String extensions correctly#350

Open
bsommerer wants to merge 1 commit intojruby:masterfrom
bsommerer:fix/nscomment-ia5string-encoding
Open

Encode Netscape IA5String extensions correctly#350
bsommerer wants to merge 1 commit intojruby:masterfrom
bsommerer:fix/nscomment-ia5string-encoding

Conversation

@bsommerer
Copy link

Summary

X509ExtensionFactory#create_ext has no special case for nsComment (OID 2.16.840.1.113730.1.13) and other Netscape IA5String extensions. They fall through to the generic else branch which double-wraps the value in OCTET STRINGs:

OCTET STRING { OCTET STRING { raw ASCII } }   -- JRuby (broken)
OCTET STRING { IA5String "..." }               -- CRuby (correct)

This causes BouncyCastle to crash when parsing certificates containing these extensions:

java.io.IOException: corrupted stream - out of bounds length found: 117 >= 34

Changes

  • Add isNetscapeIA5StringExtension() covering all Netscape extensions defined as IA5String: nsBaseUrl, nsRevocationUrl, nsCaRevocationUrl, nsRenewalUrl, nsCaPolicyUrl, nsSslServerName, nsComment
  • nsCertType (BIT STRING) is excluded as it is already handled separately
  • Add tests verifying IA5String encoding for nsComment and nsBaseUrl

How to reproduce

require 'openssl'

ef = OpenSSL::X509::ExtensionFactory.new
ext = ef.create_extension('nsComment', 'Puppet Server Internal Certificate', false)
puts ext.to_der.bytes.map { |b| '%02x' % b }.join(' ')
  • CRuby: inner bytes start with 16 22 (IA5String tag + length)
  • JRuby: inner bytes start with 04 28 (OCTET STRING tag + length)

Fixes #349

create_ext has no special case for nsComment (OID 2.16.840.1.113730.1.13)
and other Netscape IA5String extensions, so they fall through to the
generic else branch which double-wraps the value in OCTET STRINGs:

    OCTET STRING { OCTET STRING { raw ASCII } }

CRuby's native OpenSSL bindings produce the correct encoding:

    OCTET STRING { IA5String "..." }

The malformed encoding causes BouncyCastle to crash when parsing
certificates containing these extensions, as it tries to interpret the
raw ASCII bytes as ASN.1 structures.

Add isNetscapeIA5StringExtension() covering all Netscape extensions
defined as IA5String (nsBaseUrl, nsRevocationUrl, nsCaRevocationUrl,
nsRenewalUrl, nsCaPolicyUrl, nsSslServerName, nsComment). nsCertType
is excluded as it is a BIT STRING already handled separately.
@bsommerer bsommerer force-pushed the fix/nscomment-ia5string-encoding branch from 943a55d to c15ce05 Compare March 20, 2026 20:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

X509ExtensionFactory: nsComment encoded as double-wrapped OCTET STRING instead of IA5String

1 participant