@@ -1357,6 +1357,10 @@ boolean isEOC() {
1357
1357
return "EndOfContent" .equals ( getClassBaseName () );
1358
1358
}
1359
1359
1360
+ boolean isUniversal (final ThreadContext context ) {
1361
+ return "ASN1Data" .equals (getClassBaseName ()) && getTagClass (context ) == 0 ;
1362
+ }
1363
+
1360
1364
IRubyObject tagging () {
1361
1365
return getInstanceVariable ("@tagging" );
1362
1366
}
@@ -1395,16 +1399,50 @@ final ASN1TaggedObject toASN1TaggedObject(final ThreadContext context) {
1395
1399
1396
1400
final IRubyObject value = callMethod (context , "value" );
1397
1401
if (value instanceof RubyArray ) {
1402
+ // Cruby openssl joins elements of array and casts to string
1398
1403
final RubyArray arr = (RubyArray ) value ;
1399
- assert ! arr .isEmpty ();
1400
1404
1405
+ StringBuilder values = new StringBuilder ();
1401
1406
ASN1EncodableVector vec = new ASN1EncodableVector ();
1407
+
1402
1408
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
+ }
1406
1422
}
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" );
1408
1446
}
1409
1447
1410
1448
if (!(value instanceof ASN1Data )) {
@@ -1426,6 +1464,41 @@ public IRubyObject to_der(final ThreadContext context) {
1426
1464
1427
1465
byte [] toDER (final ThreadContext context ) throws IOException {
1428
1466
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
+ }
1429
1502
return toASN1 (context ).toASN1Primitive ().getEncoded (ASN1Encoding .DER );
1430
1503
}
1431
1504
@@ -1619,6 +1692,11 @@ boolean isEOC() {
1619
1692
return false ;
1620
1693
}
1621
1694
1695
+ @ Override
1696
+ boolean isUniversal (final ThreadContext context ) {
1697
+ return false ;
1698
+ }
1699
+
1622
1700
private boolean isNull () {
1623
1701
return "Null" .equals (getMetaClass ().getRealClass ().getBaseName ());
1624
1702
}
0 commit comments