@@ -1357,6 +1357,10 @@ boolean isEOC() {
13571357 return "EndOfContent" .equals ( getClassBaseName () );
13581358 }
13591359
1360+ boolean isUniversal (final ThreadContext context ) {
1361+ return "ASN1Data" .equals (getClassBaseName ()) && getTagClass (context ) == 0 ;
1362+ }
1363+
13601364 IRubyObject tagging () {
13611365 return getInstanceVariable ("@tagging" );
13621366 }
@@ -1395,16 +1399,50 @@ final ASN1TaggedObject toASN1TaggedObject(final ThreadContext context) {
13951399
13961400 final IRubyObject value = callMethod (context , "value" );
13971401 if (value instanceof RubyArray ) {
1402+ // Cruby openssl joins elements of array and casts to string
13981403 final RubyArray arr = (RubyArray ) value ;
1399- assert ! arr .isEmpty ();
14001404
1405+ StringBuilder values = new StringBuilder ();
14011406 ASN1EncodableVector vec = new ASN1EncodableVector ();
1407+
14021408 for (final IRubyObject obj : arr .toJavaArray ()) {
1403- ASN1Encodable data = ((ASN1Data ) obj ).toASN1 (context );
1404- if ( data == null ) break ;
1405- vec .add ( data );
1409+ if (obj instanceof ASN1Data ) {
1410+ ASN1Encodable data = ((ASN1Data ) obj ).toASN1 (context );
1411+ if (data == null ) break ;
1412+ vec .add (data );
1413+ } else {
1414+ final IRubyObject string = obj .checkStringType ();
1415+ if (string instanceof RubyString ) {
1416+ values .append (string .asJavaString ());
1417+ } else {
1418+ throw context .runtime .newTypeError (
1419+ "no implicit conversion of " + obj .getMetaClass ().getBaseName () + " into String" );
1420+ }
1421+ }
14061422 }
1407- return new DERTaggedObject (isExplicitTagging (), tag , new DERSequence (vec ));
1423+
1424+ if (vec .size () > 0 ) {
1425+ // array of asn1 objects as value
1426+ return new DERTaggedObject (isExplicitTagging (), tag , new DERSequence (vec ));
1427+ }
1428+
1429+ // array of strings as value (default)
1430+ return new DERTaggedObject (isExplicitTagging (), tagClass , tag ,
1431+ new DERGeneralString (values .toString ()));
1432+ } else if (value instanceof ASN1Data ) {
1433+ return new DERTaggedObject (isExplicitTagging (), tagClass , tag , ((ASN1Data ) value ).toASN1 (context ));
1434+ } else if (value instanceof RubyObject ) {
1435+ final IRubyObject string = value .checkStringType ();
1436+ if (string instanceof RubyString ) {
1437+ return new DERTaggedObject (isExplicitTagging (), tagClass , tag ,
1438+ new DERGeneralString (string .asJavaString ()));
1439+ } else {
1440+ throw context .runtime .newTypeError (
1441+ "no implicit conversion of " + value .getMetaClass ().getBaseName () + " into String" );
1442+ }
1443+ } else {
1444+ throw context .runtime .newTypeError (
1445+ "no implicit conversion of " + value .getMetaClass ().getBaseName () + " into String" );
14081446 }
14091447
14101448 if (!(value instanceof ASN1Data )) {
@@ -1426,6 +1464,41 @@ public IRubyObject to_der(final ThreadContext context) {
14261464
14271465 byte [] toDER (final ThreadContext context ) throws IOException {
14281466 if ( isEOC () ) return new byte [] { 0x00 , 0x00 };
1467+
1468+ if (isUniversal (context )) {
1469+ // handstitch conversion
1470+ final java .io .ByteArrayOutputStream out = new ByteArrayOutputStream ();
1471+ final IRubyObject value = callMethod (context , "value" );
1472+
1473+ final byte [] valueBytes ;
1474+ if (value instanceof RubyArray ) {
1475+ final RubyArray arr = (RubyArray ) value ;
1476+ final java .io .ByteArrayOutputStream valueOut = new ByteArrayOutputStream ();
1477+
1478+ for (final IRubyObject obj : arr .toJavaArray ()) {
1479+ final IRubyObject string = value .checkStringType ();
1480+ if (string instanceof RubyString ) {
1481+ valueOut .write (((RubyString ) string ).getBytes ());
1482+ } else {
1483+ throw context .runtime .newTypeError (
1484+ "no implicit conversion of " + obj .getMetaClass ().getBaseName () + " into String" );
1485+ }
1486+ }
1487+ valueBytes = valueOut .toByteArray ();
1488+ } else {
1489+ final IRubyObject string = value .checkStringType ();
1490+ if (string instanceof RubyString ) {
1491+ valueBytes = ((RubyString ) string ).getBytes ();
1492+ } else {
1493+ throw context .runtime .newTypeError (
1494+ "no implicit conversion of " + value .getMetaClass ().getBaseName () + " into String" );
1495+ }
1496+ }
1497+ out .write (getTag (context ));
1498+ out .write (valueBytes .length );
1499+ out .write (valueBytes );
1500+ return out .toByteArray ();
1501+ }
14291502 return toASN1 (context ).toASN1Primitive ().getEncoded (ASN1Encoding .DER );
14301503 }
14311504
@@ -1619,6 +1692,11 @@ boolean isEOC() {
16191692 return false ;
16201693 }
16211694
1695+ @ Override
1696+ boolean isUniversal (final ThreadContext context ) {
1697+ return false ;
1698+ }
1699+
16221700 private boolean isNull () {
16231701 return "Null" .equals (getMetaClass ().getRealClass ().getBaseName ());
16241702 }
0 commit comments