Skip to content

Commit ce773fb

Browse files
committed
[fix] ASN1 primitive tagging (encoding) part (#122)
1 parent eae9f56 commit ce773fb

File tree

2 files changed

+50
-49
lines changed

2 files changed

+50
-49
lines changed

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

+37-25
Original file line numberDiff line numberDiff line change
@@ -1336,6 +1336,10 @@ boolean isEOC() {
13361336
return "EndOfContent".equals( getClassBaseName() );
13371337
}
13381338

1339+
IRubyObject tagging() {
1340+
return getInstanceVariable("@tagging");
1341+
}
1342+
13391343
boolean isExplicitTagging() { return ! isImplicitTagging(); }
13401344

13411345
boolean isImplicitTagging() { return true; }
@@ -1364,19 +1368,24 @@ ASN1Encodable toASN1(final ThreadContext context) {
13641368
final ASN1TaggedObject toASN1TaggedObject(final ThreadContext context) {
13651369
final int tag = getTag(context);
13661370

1367-
final IRubyObject val = callMethod(context, "value");
1368-
if ( val instanceof RubyArray ) {
1369-
final RubyArray arr = (RubyArray) val;
1371+
final IRubyObject value = callMethod(context, "value");
1372+
if (value instanceof RubyArray) {
1373+
final RubyArray arr = (RubyArray) value;
13701374
assert ! arr.isEmpty();
13711375

13721376
ASN1EncodableVector vec = new ASN1EncodableVector();
1373-
for ( final IRubyObject obj : arr.toJavaArray() ) {
1377+
for (final IRubyObject obj : arr.toJavaArray()) {
13741378
ASN1Encodable data = ((ASN1Data) obj).toASN1(context);
1375-
if ( data == null ) break; vec.add( data );
1379+
if ( data == null ) break;
1380+
vec.add( data );
13761381
}
13771382
return new DERTaggedObject(isExplicitTagging(), tag, new DERSequence(vec));
13781383
}
1379-
return new DERTaggedObject(isExplicitTagging(), tag, ((ASN1Data) val).toASN1(context));
1384+
1385+
if (!(value instanceof ASN1Data)) {
1386+
throw new UnsupportedOperationException("toASN1 " + inspect() + " value: " + value.inspect() + " (" + value.getMetaClass() + ")");
1387+
}
1388+
return new DERTaggedObject(isExplicitTagging(), tag, ((ASN1Data) value).toASN1(context));
13801389
}
13811390

13821391
@JRubyMethod
@@ -1559,9 +1568,13 @@ static void initializeImpl(final ThreadContext context,
15591568
self.setInstanceVariable("@indefinite_length", runtime.getFalse());
15601569
}
15611570

1571+
boolean isTagged() {
1572+
return !tagging().isNil();
1573+
}
1574+
15621575
@Override
15631576
boolean isExplicitTagging() {
1564-
return "EXPLICIT".equals( getInstanceVariable("@tagging").toString() );
1577+
return "EXPLICIT".equals( tagging().toString() );
15651578
}
15661579

15671580
@Override
@@ -1581,19 +1594,16 @@ byte[] toDER(final ThreadContext context) throws IOException {
15811594
return toASN1(context).toASN1Primitive().getEncoded(ASN1Encoding.DER);
15821595
}
15831596

1584-
/*
1585-
private static final Class DERBooleanClass;
1586-
static {
1587-
Class klass;
1588-
try {
1589-
klass = Class.forName("org.bouncycastle.asn1.DERBoolean");
1590-
}
1591-
catch(ClassNotFoundException e) { klass = null; }
1592-
DERBooleanClass = klass;
1593-
} */
1594-
15951597
@Override
15961598
ASN1Encodable toASN1(final ThreadContext context) {
1599+
final ASN1Encodable primitive = toASN1Primitive(context);
1600+
if (isTagged()) {
1601+
return new DERTaggedObject(isExplicitTagging(), getTagClass(context), getTag(context), primitive);
1602+
}
1603+
return primitive;
1604+
}
1605+
1606+
private ASN1Encodable toASN1Primitive(final ThreadContext context) {
15971607
Class<? extends ASN1Encodable> type = typeClass( getMetaClass() );
15981608
if ( type == null ) {
15991609
final int tag = getTag(context);
@@ -1691,9 +1701,9 @@ ASN1Encodable toASN1(final ThreadContext context) {
16911701
}
16921702

16931703
if (isDebug(context.runtime)) {
1694-
debug(this + " toASN1() could not handle class " + getMetaClass() + " and value " + val.inspect() + " (" + val.getClass().getName() + ")");
1704+
debug(this + " toASN1() could not handle class " + getMetaClass() + " and value: " + val.inspect() + " (" + val.getMetaClass() + ")");
16951705
}
1696-
throw context.runtime.newNotImplementedError("unimplemented method called: OpenSSL::ASN1Data#toASN1 (" + type + ")");
1706+
throw new UnsupportedOperationException("OpenSSL::ASN1Data#toASN1 (" + type + ") not implemented"); // should not happen
16971707
}
16981708

16991709
private static char[] toBMPChars(final ByteList string) {
@@ -1785,15 +1795,18 @@ private boolean isInfiniteLength() {
17851795
return getInstanceVariable("@indefinite_length").isTrue();
17861796
}
17871797

1798+
private boolean isTagged() {
1799+
return !tagging().isNil();
1800+
}
1801+
17881802
@Override
17891803
boolean isExplicitTagging() {
1790-
IRubyObject tagging = getInstanceVariable("@tagging");
1791-
return tagging.isNil() || "EXPLICIT".equals( tagging.toString() );
1804+
return "EXPLICIT".equals( tagging().toString() ); // nil.toString() == ""
17921805
}
17931806

17941807
@Override
17951808
boolean isImplicitTagging() {
1796-
return "IMPLICIT".equals( getInstanceVariable("@tagging").toString() );
1809+
return "IMPLICIT".equals( tagging().toString() );
17971810
}
17981811

17991812
@Override
@@ -1940,8 +1953,7 @@ public ASN1Primitive toASN1Primitive() {
19401953

19411954
}
19421955

1943-
private static boolean addEntry(final ThreadContext context,
1944-
final ASN1EncodableVector vec, final IRubyObject entry) {
1956+
private static boolean addEntry(final ThreadContext context, final ASN1EncodableVector vec, final IRubyObject entry) {
19451957
try {
19461958
if ( entry instanceof Constructive ) {
19471959
final Constructive constructive = (Constructive) entry;

src/test/ruby/test_asn1.rb

+13-24
Original file line numberDiff line numberDiff line change
@@ -608,35 +608,25 @@ def test_constructive
608608
end
609609

610610
def test_prim_explicit_tagging
611-
# TODO: Import Issue
612-
# <"\xA0\x03\x04\x01a"> expected but was <"\x04\x01a">
613-
#oct_str = OpenSSL::ASN1::OctetString.new("a", 0, :EXPLICIT)
614-
#encode_test B(%w{ A0 03 04 01 61 }), oct_str
615-
# <"a\x03\x04\x01a"> expected but was <"\x04\x01a">
611+
oct_str = OpenSSL::ASN1::OctetString.new("a", 0, :EXPLICIT)
612+
encode_test B(%w{ A0 03 04 01 61 }), oct_str
616613
oct_str2 = OpenSSL::ASN1::OctetString.new("a", 1, :EXPLICIT, :APPLICATION)
617-
#encode_test B(%w{ 61 03 04 01 61 }), oct_str2
614+
encode_test B(%w{ 61 03 04 01 61 }), oct_str2
618615

619616
decoded = OpenSSL::ASN1.decode(oct_str2.to_der)
620-
# <:APPLICATION> expected but was <:UNIVERSAL>
621-
#assert_equal :APPLICATION, decoded.tag_class
622-
# <1> expected but was <4>
623-
#assert_equal 1, decoded.tag
617+
assert_equal :APPLICATION, decoded.tag_class
618+
assert_equal 1, decoded.tag
624619
assert_equal 1, decoded.value.size
625-
#inner = decoded.value[0]
626-
# <OpenSSL::ASN1::OctetString> expected but was <String>
627-
#assert_equal OpenSSL::ASN1::OctetString, inner.class
628-
# NoMethodError: undefined method `value' for "a":String
629-
#assert_equal B(%w{ 61 }), inner.value
620+
inner = decoded.value[0]
621+
assert_equal OpenSSL::ASN1::OctetString, inner.class
622+
assert_equal B(%w{ 61 }), inner.value
630623
end
631624

632625
def test_prim_implicit_tagging
633-
#int = OpenSSL::ASN1::Integer.new(1, 0, :IMPLICIT)
634-
# TODO: Import Issue
635-
# <"\x80\x01\x01"> expected but was <"\x02\x01\x01">
636-
#encode_test B(%w{ 80 01 01 }), int
637-
#int2 = OpenSSL::ASN1::Integer.new(1, 1, :IMPLICIT, :APPLICATION)
638-
# <"A\x01\x01"> expected but was <"\x02\x01\x01">
639-
#encode_test B(%w{ 41 01 01 }), int2
626+
int = OpenSSL::ASN1::Integer.new(1, 0, :IMPLICIT)
627+
encode_test B(%w{ 80 01 01 }), int
628+
int2 = OpenSSL::ASN1::Integer.new(1, 1, :IMPLICIT, :APPLICATION)
629+
encode_test B(%w{ 41 01 01 }), int2
640630
#decoded = OpenSSL::ASN1.decode(int2.to_der)
641631
# <:APPLICATION> expected but was <:UNIVERSAL>
642632
#assert_equal :APPLICATION, decoded.tag_class
@@ -907,8 +897,7 @@ def test_raw_constructive
907897
nil,
908898
:UNIVERSAL )
909899
assert_equal false, inf_octets.infinite_length
910-
# The real value of inf_octets is "\x01\x02", i.e. the concatenation
911-
# of partial1 and partial2
900+
# The real value of inf_octets is "\x01\x02", i.e. the concatenation of partial1 and partial2
912901
inf_octets.infinite_length = true
913902
assert_equal true, inf_octets.infinite_length
914903

0 commit comments

Comments
 (0)