Skip to content

Commit d2b2384

Browse files
to_der on ASN1Data should convert ruby strings into java strings before encoding
1 parent 97798e0 commit d2b2384

File tree

2 files changed

+112
-5
lines changed

2 files changed

+112
-5
lines changed

src/main/java/org/jruby/ext/openssl/ASN1.java

+82-5
Original file line numberDiff line numberDiff line change
@@ -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+
String values = new String();
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 = values.concat(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));
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,40 @@ 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+
String values = new String();
1476+
final RubyArray arr = (RubyArray) value;
1477+
for (final IRubyObject obj : arr.toJavaArray()) {
1478+
final IRubyObject string = value.checkStringType();
1479+
if (string instanceof RubyString) {
1480+
values = values + string;
1481+
} else {
1482+
throw context.runtime.newTypeError(
1483+
"no implicit conversion of " + obj.getMetaClass().getBaseName() + " into String");
1484+
}
1485+
}
1486+
valueBytes = values.getBytes();
1487+
} else {
1488+
final IRubyObject string = value.checkStringType();
1489+
if (string instanceof RubyString) {
1490+
valueBytes = ((RubyString) string).getBytes();
1491+
} else {
1492+
throw context.runtime.newTypeError(
1493+
"no implicit conversion of " + value.getMetaClass().getBaseName() + " into String");
1494+
}
1495+
}
1496+
out.write(getTag(context));
1497+
out.write(valueBytes.length);
1498+
out.write(valueBytes);
1499+
return out.toByteArray();
1500+
}
14291501
return toASN1(context).toASN1Primitive().getEncoded(ASN1Encoding.DER);
14301502
}
14311503

@@ -1619,6 +1691,11 @@ boolean isEOC() {
16191691
return false;
16201692
}
16211693

1694+
@Override
1695+
boolean isUniversal(final ThreadContext context) {
1696+
return false;
1697+
}
1698+
16221699
private boolean isNull() {
16231700
return "Null".equals(getMetaClass().getRealClass().getBaseName());
16241701
}

src/test/ruby/test_asn1.rb

+30
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,36 @@ def test_null
251251
}
252252
end
253253

254+
def test_encode_asn1_data
255+
ai = OpenSSL::ASN1::ASN1Data.new(i = "bla", 0, :APPLICATION)
256+
ai2 = OpenSSL::ASN1.decode(ai.to_der)
257+
assert_equal :APPLICATION, ai2.tag_class
258+
assert_equal 0, ai2.tag
259+
assert_equal i, ai2.value
260+
261+
ai = OpenSSL::ASN1::ASN1Data.new(i = "bla", 4, :UNIVERSAL)
262+
ai2 = OpenSSL::ASN1.decode(ai.to_der)
263+
assert_equal :UNIVERSAL, ai2.tag_class
264+
assert_equal 4, ai2.tag
265+
assert_equal i, ai2.value
266+
267+
ai = OpenSSL::ASN1::ASN1Data.new(i = ["bla"], 0, :APPLICATION)
268+
ai2 = OpenSSL::ASN1.decode(ai.to_der)
269+
assert_equal :APPLICATION, ai2.tag_class
270+
assert_equal 0, ai2.tag
271+
assert_equal "bla", ai2.value
272+
273+
ai = OpenSSL::ASN1::ASN1Data.new(i = ["bla", "bla"], 0, :APPLICATION)
274+
ai2 = OpenSSL::ASN1.decode(ai.to_der)
275+
assert_equal :APPLICATION, ai2.tag_class
276+
assert_equal 0, ai2.tag
277+
assert_equal "blabla", ai2.value
278+
279+
assert_raise(ArgumentError) { OpenSSL::ASN1::ASN1Data.new(1).to_der }
280+
assert_raise("no implicit conversion of Integer into String") { OpenSSL::ASN1::ASN1Data.new(1, 0, :APPLICATION).to_der }
281+
assert_raise("no implicit conversion of Integer into String") { OpenSSL::ASN1::ASN1Data.new(1, 0, :CONTEXT_SPECIFIC).to_der }
282+
end
283+
254284
def test_encode_nil
255285
#Primitives raise TypeError, Constructives NoMethodError
256286

0 commit comments

Comments
 (0)