@@ -1071,15 +1071,14 @@ else if ( obj instanceof ASN1GraphicString ) {
10711071 break ;
10721072 }
10731073
1074- if ( taggedObj . getTagClass () == BERTags . APPLICATION ) {
1074+ try {
10751075 final ASN1Sequence sequence = (ASN1Sequence ) taggedObj .getBaseUniversal (false , SEQUENCE );
10761076 @ SuppressWarnings ("unchecked" )
10771077 final RubyArray valArr = decodeObjects (context , ASN1 , sequence .getObjects ());
10781078 return ASN1 .getClass ("ASN1Data" ).newInstance (context , new IRubyObject [] { valArr , tag , tag_class }, Block .NULL_BLOCK );
1079- } else {
1080- IRubyObject val = decodeObject (context , ASN1 , taggedObj .getBaseObject ());
1081- final RubyArray valArr = runtime .newArray (val );
1082- return ASN1 .getClass ("ASN1Data" ).newInstance (context , new IRubyObject [] { valArr , tag , tag_class }, Block .NULL_BLOCK );
1079+ } catch (IllegalStateException e ) {
1080+ IRubyObject val = decodeObject (context , ASN1 , taggedObj .getBaseObject ()).callMethod (context , "value" );
1081+ return ASN1 .getClass ("ASN1Data" ).newInstance (context , new IRubyObject [] { val , tag , tag_class }, Block .NULL_BLOCK );
10831082 }
10841083 }
10851084
@@ -1357,6 +1356,10 @@ boolean isEOC() {
13571356 return "EndOfContent" .equals ( getClassBaseName () );
13581357 }
13591358
1359+ boolean isUniversal (final ThreadContext context ) {
1360+ return "ASN1Data" .equals (getClassBaseName ()) && getTagClass (context ) == 0 ;
1361+ }
1362+
13601363 IRubyObject tagging () {
13611364 return getInstanceVariable ("@tagging" );
13621365 }
@@ -1395,22 +1398,51 @@ final ASN1TaggedObject toASN1TaggedObject(final ThreadContext context) {
13951398
13961399 final IRubyObject value = callMethod (context , "value" );
13971400 if (value instanceof RubyArray ) {
1401+ // Cruby openssl joins elements of array and casts to string
13981402 final RubyArray arr = (RubyArray ) value ;
1399- assert ! arr .isEmpty ();
14001403
1404+ StringBuilder values = new StringBuilder ();
14011405 ASN1EncodableVector vec = new ASN1EncodableVector ();
1406+
14021407 for (final IRubyObject obj : arr .toJavaArray ()) {
1403- ASN1Encodable data = ((ASN1Data ) obj ).toASN1 (context );
1404- if ( data == null ) break ;
1405- vec .add ( data );
1408+ if (obj instanceof ASN1Data ) {
1409+ ASN1Encodable data = ((ASN1Data ) obj ).toASN1 (context );
1410+ if (data == null ) break ;
1411+ vec .add (data );
1412+ } else {
1413+ final IRubyObject string = obj .checkStringType ();
1414+ if (string instanceof RubyString ) {
1415+ values .append (string .asJavaString ());
1416+ } else {
1417+ throw context .runtime .newTypeError (
1418+ "no implicit conversion of " + obj .getMetaClass ().getBaseName () + " into String" );
1419+ }
1420+ }
14061421 }
1407- return new DERTaggedObject (isExplicitTagging (), tag , new DERSequence (vec ));
1408- }
14091422
1410- if (!(value instanceof ASN1Data )) {
1411- throw new UnsupportedOperationException ("toASN1 " + inspect () + " value: " + value .inspect () + " (" + value .getMetaClass () + ")" );
1423+ if (vec .size () > 0 ) {
1424+ // array of asn1 objects as value
1425+ return new DERTaggedObject (isExplicitTagging (), tag , new DERSequence (vec ));
1426+ }
1427+
1428+ // array of strings as value (default)
1429+ return new DERTaggedObject (isExplicitTagging (), tagClass , tag ,
1430+ new DERGeneralString (values .toString ()));
1431+ } else if (value instanceof ASN1Data ) {
1432+ return new DERTaggedObject (isExplicitTagging (), tagClass , tag , ((ASN1Data ) value ).toASN1 (context ));
1433+ } else if (value instanceof RubyObject ) {
1434+ final IRubyObject string = value .checkStringType ();
1435+ if (string instanceof RubyString ) {
1436+ return new DERTaggedObject (isExplicitTagging (), tagClass , tag ,
1437+ new DERGeneralString (string .asJavaString ()));
1438+ } else {
1439+ throw context .runtime .newTypeError (
1440+ "no implicit conversion of " + value .getMetaClass ().getBaseName () + " into String" );
1441+ }
1442+ } else {
1443+ throw context .runtime .newTypeError (
1444+ "no implicit conversion of " + value .getMetaClass ().getBaseName () + " into String" );
14121445 }
1413- return new DERTaggedObject (isExplicitTagging (), tagClass , tag , ((ASN1Data ) value ).toASN1 (context ));
14141446 }
14151447
14161448 @ JRubyMethod
@@ -1426,6 +1458,41 @@ public IRubyObject to_der(final ThreadContext context) {
14261458
14271459 byte [] toDER (final ThreadContext context ) throws IOException {
14281460 if ( isEOC () ) return new byte [] { 0x00 , 0x00 };
1461+
1462+ if (isUniversal (context )) {
1463+ // handstitch conversion
1464+ final java .io .ByteArrayOutputStream out = new ByteArrayOutputStream ();
1465+ final IRubyObject value = callMethod (context , "value" );
1466+
1467+ final byte [] valueBytes ;
1468+ if (value instanceof RubyArray ) {
1469+ final RubyArray arr = (RubyArray ) value ;
1470+ final java .io .ByteArrayOutputStream valueOut = new ByteArrayOutputStream ();
1471+
1472+ for (final IRubyObject obj : arr .toJavaArray ()) {
1473+ final IRubyObject string = value .checkStringType ();
1474+ if (string instanceof RubyString ) {
1475+ valueOut .write (((RubyString ) string ).getBytes ());
1476+ } else {
1477+ throw context .runtime .newTypeError (
1478+ "no implicit conversion of " + obj .getMetaClass ().getBaseName () + " into String" );
1479+ }
1480+ }
1481+ valueBytes = valueOut .toByteArray ();
1482+ } else {
1483+ final IRubyObject string = value .checkStringType ();
1484+ if (string instanceof RubyString ) {
1485+ valueBytes = ((RubyString ) string ).getBytes ();
1486+ } else {
1487+ throw context .runtime .newTypeError (
1488+ "no implicit conversion of " + value .getMetaClass ().getBaseName () + " into String" );
1489+ }
1490+ }
1491+ out .write (getTag (context ));
1492+ out .write (valueBytes .length );
1493+ out .write (valueBytes );
1494+ return out .toByteArray ();
1495+ }
14291496 return toASN1 (context ).toASN1Primitive ().getEncoded (ASN1Encoding .DER );
14301497 }
14311498
@@ -1619,6 +1686,11 @@ boolean isEOC() {
16191686 return false ;
16201687 }
16211688
1689+ @ Override
1690+ boolean isUniversal (final ThreadContext context ) {
1691+ return false ;
1692+ }
1693+
16221694 private boolean isNull () {
16231695 return "Null" .equals (getMetaClass ().getRealClass ().getBaseName ());
16241696 }
0 commit comments