@@ -1071,15 +1071,14 @@ else if ( obj instanceof ASN1GraphicString ) {
1071
1071
break ;
1072
1072
}
1073
1073
1074
- if ( taggedObj . getTagClass () == BERTags . APPLICATION ) {
1074
+ try {
1075
1075
final ASN1Sequence sequence = (ASN1Sequence ) taggedObj .getBaseUniversal (false , SEQUENCE );
1076
1076
@ SuppressWarnings ("unchecked" )
1077
1077
final RubyArray valArr = decodeObjects (context , ASN1 , sequence .getObjects ());
1078
1078
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 );
1083
1082
}
1084
1083
}
1085
1084
@@ -1357,6 +1356,10 @@ boolean isEOC() {
1357
1356
return "EndOfContent" .equals ( getClassBaseName () );
1358
1357
}
1359
1358
1359
+ boolean isUniversal (final ThreadContext context ) {
1360
+ return "ASN1Data" .equals (getClassBaseName ()) && getTagClass (context ) == 0 ;
1361
+ }
1362
+
1360
1363
IRubyObject tagging () {
1361
1364
return getInstanceVariable ("@tagging" );
1362
1365
}
@@ -1395,22 +1398,51 @@ final ASN1TaggedObject toASN1TaggedObject(final ThreadContext context) {
1395
1398
1396
1399
final IRubyObject value = callMethod (context , "value" );
1397
1400
if (value instanceof RubyArray ) {
1401
+ // Cruby openssl joins elements of array and casts to string
1398
1402
final RubyArray arr = (RubyArray ) value ;
1399
- assert ! arr .isEmpty ();
1400
1403
1404
+ StringBuilder values = new StringBuilder ();
1401
1405
ASN1EncodableVector vec = new ASN1EncodableVector ();
1406
+
1402
1407
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
+ }
1406
1421
}
1407
- return new DERTaggedObject (isExplicitTagging (), tag , new DERSequence (vec ));
1408
- }
1409
1422
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" );
1412
1445
}
1413
- return new DERTaggedObject (isExplicitTagging (), tagClass , tag , ((ASN1Data ) value ).toASN1 (context ));
1414
1446
}
1415
1447
1416
1448
@ JRubyMethod
@@ -1426,6 +1458,41 @@ public IRubyObject to_der(final ThreadContext context) {
1426
1458
1427
1459
byte [] toDER (final ThreadContext context ) throws IOException {
1428
1460
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
+ }
1429
1496
return toASN1 (context ).toASN1Primitive ().getEncoded (ASN1Encoding .DER );
1430
1497
}
1431
1498
@@ -1619,6 +1686,11 @@ boolean isEOC() {
1619
1686
return false ;
1620
1687
}
1621
1688
1689
+ @ Override
1690
+ boolean isUniversal (final ThreadContext context ) {
1691
+ return false ;
1692
+ }
1693
+
1622
1694
private boolean isNull () {
1623
1695
return "Null" .equals (getMetaClass ().getRealClass ().getBaseName ());
1624
1696
}
0 commit comments