diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 3ec390f55e..a9172ad97f 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -66,9 +66,9 @@ jobs: # If the Autobuild fails above, remove it and uncomment the following three lines. # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. - # - run: | - # echo "Run, Build Application using script" - # gradle clean build + - run: | + echo "Run, Build Application using script" + gradle clean build - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v2 diff --git a/.gitignore b/.gitignore index 72ab296f63..b2e0c1adcb 100644 --- a/.gitignore +++ b/.gitignore @@ -28,4 +28,10 @@ codesigning.jks /prov/src/main/core/ -bc-build.user.properties \ No newline at end of file +bc-build.user.properties + +# files created during tests +mail/compressed.message +mail/encrypted.message +mail/id.p12 +mail/signed.message diff --git a/core/src/main/java/org/bouncycastle/asn1/ASN1BitString.java b/core/src/main/java/org/bouncycastle/asn1/ASN1BitString.java index aff52097a1..111ae85789 100644 --- a/core/src/main/java/org/bouncycastle/asn1/ASN1BitString.java +++ b/core/src/main/java/org/bouncycastle/asn1/ASN1BitString.java @@ -237,22 +237,22 @@ public ASN1BitStringParser parser() */ public String getString() { - byte[] string; + byte[] encoded; try { - string = getEncoded(); + encoded = getEncoded(); } catch (IOException e) { throw new ASN1ParsingException("Internal error encoding BitString: " + e.getMessage(), e); } - StringBuffer buf = new StringBuffer(1 + string.length * 2); + final StringBuilder buf = new StringBuilder(1 + encoded.length * 2); buf.append('#'); - for (int i = 0; i != string.length; i++) + for (int i = 0; i != encoded.length; i++) { - byte b = string[i]; + byte b = encoded[i]; buf.append(table[(b >>> 4) & 0xf]); buf.append(table[b & 0xf]); } diff --git a/core/src/main/java/org/bouncycastle/asn1/ASN1RelativeOID.java b/core/src/main/java/org/bouncycastle/asn1/ASN1RelativeOID.java index aff4b89b3b..0f4d4264cd 100644 --- a/core/src/main/java/org/bouncycastle/asn1/ASN1RelativeOID.java +++ b/core/src/main/java/org/bouncycastle/asn1/ASN1RelativeOID.java @@ -300,7 +300,7 @@ else if ('0' <= ch && ch <= '9') static String parseContents(byte[] contents) { - StringBuilder objId = new StringBuilder(); + final StringBuilder objId = new StringBuilder(); long value = 0; BigInteger bigValue = null; boolean first = true; diff --git a/core/src/main/java/org/bouncycastle/asn1/util/ASN1Dump.java b/core/src/main/java/org/bouncycastle/asn1/util/ASN1Dump.java index 4ff5e2dcd9..b40ff7c363 100644 --- a/core/src/main/java/org/bouncycastle/asn1/util/ASN1Dump.java +++ b/core/src/main/java/org/bouncycastle/asn1/util/ASN1Dump.java @@ -1,50 +1,19 @@ package org.bouncycastle.asn1.util; -import org.bouncycastle.asn1.ASN1BMPString; -import org.bouncycastle.asn1.ASN1BitString; -import org.bouncycastle.asn1.ASN1Boolean; -import org.bouncycastle.asn1.ASN1Encodable; -import org.bouncycastle.asn1.ASN1Enumerated; -import org.bouncycastle.asn1.ASN1External; -import org.bouncycastle.asn1.ASN1GeneralizedTime; -import org.bouncycastle.asn1.ASN1GraphicString; -import org.bouncycastle.asn1.ASN1IA5String; -import org.bouncycastle.asn1.ASN1Integer; -import org.bouncycastle.asn1.ASN1Null; -import org.bouncycastle.asn1.ASN1NumericString; -import org.bouncycastle.asn1.ASN1ObjectDescriptor; -import org.bouncycastle.asn1.ASN1ObjectIdentifier; -import org.bouncycastle.asn1.ASN1OctetString; -import org.bouncycastle.asn1.ASN1Primitive; -import org.bouncycastle.asn1.ASN1PrintableString; -import org.bouncycastle.asn1.ASN1RelativeOID; -import org.bouncycastle.asn1.ASN1Sequence; -import org.bouncycastle.asn1.ASN1Set; -import org.bouncycastle.asn1.ASN1T61String; -import org.bouncycastle.asn1.ASN1TaggedObject; -import org.bouncycastle.asn1.ASN1UTCTime; -import org.bouncycastle.asn1.ASN1UTF8String; -import org.bouncycastle.asn1.ASN1Util; -import org.bouncycastle.asn1.ASN1VideotexString; -import org.bouncycastle.asn1.ASN1VisibleString; -import org.bouncycastle.asn1.BEROctetString; -import org.bouncycastle.asn1.BERSequence; -import org.bouncycastle.asn1.BERSet; -import org.bouncycastle.asn1.BERTaggedObject; -import org.bouncycastle.asn1.DERBitString; -import org.bouncycastle.asn1.DERSequence; -import org.bouncycastle.asn1.DERSet; -import org.bouncycastle.asn1.DERTaggedObject; -import org.bouncycastle.asn1.DLBitString; +import org.bouncycastle.asn1.*; import org.bouncycastle.util.Strings; import org.bouncycastle.util.encoders.Hex; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.util.Objects; + /** * Utility class for dumping ASN.1 objects as (hopefully) human friendly strings. */ public class ASN1Dump { - private static final String TAB = " "; + private static final String NL = System.lineSeparator(); private static final int SAMPLE_SIZE = 32; /** @@ -53,245 +22,165 @@ public class ASN1Dump * @param obj the ASN1Primitive to be dumped out. */ static void _dumpAsString( - String indent, - boolean verbose, + //String indent, + boolean verbose, ASN1Primitive obj, - StringBuffer buf) + IndentingAppendable buf) { - String nl = Strings.lineSeparator(); - if (obj instanceof ASN1Null) - { - buf.append(indent); - buf.append("NULL"); - buf.append(nl); - } - else if (obj instanceof ASN1Sequence) - { - buf.append(indent); - if (obj instanceof BERSequence) - { - buf.append("BER Sequence"); - } - else if (obj instanceof DERSequence) - { - buf.append("DER Sequence"); - } - else - { - buf.append("Sequence"); + if (obj instanceof ASN1Null) { + buf.appendIndentedLine("NULL"); + } else if (obj instanceof ASN1Sequence) { + if (obj instanceof BERSequence) { + buf.appendIndentedLine("BER Sequence"); + } else if (obj instanceof DERSequence) { + buf.appendIndentedLine("DER Sequence"); + } else { + buf.appendIndentedLine("Sequence"); } - buf.append(nl); - ASN1Sequence sequence = (ASN1Sequence)obj; - String elementsIndent = indent + TAB; + final ASN1Sequence sequence = (ASN1Sequence) obj; - for (int i = 0, count = sequence.size(); i < count; ++i) - { - _dumpAsString(elementsIndent, verbose, sequence.getObjectAt(i).toASN1Primitive(), buf); - } - } - else if (obj instanceof ASN1Set) - { - buf.append(indent); - if (obj instanceof BERSet) - { - buf.append("BER Set"); + buf.incrementIndentLevel(); + for (ASN1Encodable it : sequence) { + _dumpAsString(verbose, it.toASN1Primitive(), buf); } - else if (obj instanceof DERSet) - { - buf.append("DER Set"); - } - else - { - buf.append("Set"); + buf.decrementIndentLevel(); + } else if (obj instanceof ASN1Set) { + final String description; + if (obj instanceof BERSet) { + description = "BER Set"; + } else if (obj instanceof DERSet) { + description = "DER Set"; + } else { + description = "Set"; } - buf.append(nl); + buf.appendIndentedLine(description); - ASN1Set set = (ASN1Set)obj; - String elementsIndent = indent + TAB; - - for (int i = 0, count = set.size(); i < count; ++i) - { - _dumpAsString(elementsIndent, verbose, set.getObjectAt(i).toASN1Primitive(), buf); + final ASN1Set set = (ASN1Set) obj; + buf.incrementIndentLevel(); + for (int i = 0, count = set.size(); i < count; ++i) { + _dumpAsString(verbose, set.getObjectAt(i).toASN1Primitive(), buf); } - } - else if (obj instanceof ASN1TaggedObject) - { - buf.append(indent); - if (obj instanceof BERTaggedObject) - { + buf.decrementIndentLevel(); + } else if (obj instanceof ASN1TaggedObject) { + buf.appendIndent(); + if (obj instanceof BERTaggedObject) { buf.append("BER Tagged "); - } - else if (obj instanceof DERTaggedObject) - { + } else if (obj instanceof DERTaggedObject) { buf.append("DER Tagged "); - } - else - { + } else { buf.append("Tagged "); } - ASN1TaggedObject o = (ASN1TaggedObject)obj; - + final ASN1TaggedObject o = (ASN1TaggedObject) obj; buf.append(ASN1Util.getTagText(o)); - - if (!o.isExplicit()) - { + if (!o.isExplicit()) { buf.append(" IMPLICIT "); } - - buf.append(nl); - - String baseIndent = indent + TAB; - - _dumpAsString(baseIndent, verbose, o.getBaseObject().toASN1Primitive(), buf); - } - else if (obj instanceof ASN1OctetString) - { - ASN1OctetString oct = (ASN1OctetString)obj; - - if (obj instanceof BEROctetString) - { - buf.append(indent + "BER Constructed Octet String" + "[" + oct.getOctets().length + "] "); - } - else - { - buf.append(indent + "DER Octet String" + "[" + oct.getOctets().length + "] "); + buf.appendLine().incrementIndentLevel(); + _dumpAsString(verbose, o.getBaseObject().toASN1Primitive(), buf); + buf.decrementIndentLevel(); + } else if (obj instanceof ASN1OctetString) { + final ASN1OctetString oct = (ASN1OctetString) obj; + if (obj instanceof BEROctetString) { + buf.appendIndentedLine("BER Constructed Octet String[" + oct.getOctets().length + "]"); + } else { + buf.appendIndentedLine("DER Octet String[" + oct.getOctets().length + "]"); } - if (verbose) - { - buf.append(dumpBinaryDataAsString(indent, oct.getOctets())); + if (verbose) { + dumpBinaryDataAsString(buf, oct.getOctets()); + } else { + buf.append(NL); } - else - { - buf.append(nl); + } else if (obj instanceof ASN1ObjectIdentifier) { + buf.appendIndentedLine(toASN1String("ObjectIdentifier", ((ASN1ObjectIdentifier) obj).getId())); + } else if (obj instanceof ASN1RelativeOID) { + buf.appendIndentedLine(toASN1String("RelativeOID", ((ASN1RelativeOID) obj).getId())); + } else if (obj instanceof ASN1Boolean) { + buf.appendIndentedLine(toASN1String("Boolean", ((ASN1Boolean) obj).isTrue())); + } else if (obj instanceof ASN1Integer) { + buf.appendIndentedLine(toASN1String("Integer", ((ASN1Integer) obj).getValue())); + } else if (obj instanceof ASN1BitString) { + final ASN1BitString bitString = (ASN1BitString) obj; + final String line; + if (bitString instanceof DERBitString) { + line = toASN1BitString("DER Bit String", bitString); + } else if (bitString instanceof DLBitString) { + line = toASN1BitString("DL Bit String", bitString); + } else { + line = toASN1BitString("BER Bit String", bitString); } - } - else if (obj instanceof ASN1ObjectIdentifier) - { - buf.append(indent + "ObjectIdentifier(" + ((ASN1ObjectIdentifier)obj).getId() + ")" + nl); - } - else if (obj instanceof ASN1RelativeOID) - { - buf.append(indent + "RelativeOID(" + ((ASN1RelativeOID)obj).getId() + ")" + nl); - } - else if (obj instanceof ASN1Boolean) - { - buf.append(indent + "Boolean(" + ((ASN1Boolean)obj).isTrue() + ")" + nl); - } - else if (obj instanceof ASN1Integer) - { - buf.append(indent + "Integer(" + ((ASN1Integer)obj).getValue() + ")" + nl); - } - else if (obj instanceof ASN1BitString) - { - ASN1BitString bitString = (ASN1BitString)obj; - - byte[] bytes = bitString.getBytes(); - int padBits = bitString.getPadBits(); + buf.appendIndentedLine(line); - if (bitString instanceof DERBitString) - { - buf.append(indent + "DER Bit String" + "[" + bytes.length + ", " + padBits + "] "); - } - else if (bitString instanceof DLBitString) - { - buf.append(indent + "DL Bit String" + "[" + bytes.length + ", " + padBits + "] "); - } - else - { - buf.append(indent + "BER Bit String" + "[" + bytes.length + ", " + padBits + "] "); - } - - if (verbose) - { - buf.append(dumpBinaryDataAsString(indent, bytes)); + if (verbose) { + dumpBinaryDataAsString(buf, bitString.getBytes()); + } else { + buf.appendLine(); } - else - { - buf.append(nl); - } - } - else if (obj instanceof ASN1IA5String) - { - buf.append(indent + "IA5String(" + ((ASN1IA5String)obj).getString() + ") " + nl); - } - else if (obj instanceof ASN1UTF8String) - { - buf.append(indent + "UTF8String(" + ((ASN1UTF8String)obj).getString() + ") " + nl); - } - else if (obj instanceof ASN1NumericString) - { - buf.append(indent + "NumericString(" + ((ASN1NumericString)obj).getString() + ") " + nl); - } - else if (obj instanceof ASN1PrintableString) - { - buf.append(indent + "PrintableString(" + ((ASN1PrintableString)obj).getString() + ") " + nl); - } - else if (obj instanceof ASN1VisibleString) - { - buf.append(indent + "VisibleString(" + ((ASN1VisibleString)obj).getString() + ") " + nl); - } - else if (obj instanceof ASN1BMPString) - { - buf.append(indent + "BMPString(" + ((ASN1BMPString)obj).getString() + ") " + nl); - } - else if (obj instanceof ASN1T61String) - { - buf.append(indent + "T61String(" + ((ASN1T61String)obj).getString() + ") " + nl); - } - else if (obj instanceof ASN1GraphicString) - { - buf.append(indent + "GraphicString(" + ((ASN1GraphicString)obj).getString() + ") " + nl); - } - else if (obj instanceof ASN1VideotexString) - { - buf.append(indent + "VideotexString(" + ((ASN1VideotexString)obj).getString() + ") " + nl); - } - else if (obj instanceof ASN1UTCTime) - { - buf.append(indent + "UTCTime(" + ((ASN1UTCTime)obj).getTime() + ") " + nl); - } - else if (obj instanceof ASN1GeneralizedTime) - { - buf.append(indent + "GeneralizedTime(" + ((ASN1GeneralizedTime)obj).getTime() + ") " + nl); - } - else if (obj instanceof ASN1Enumerated) - { - ASN1Enumerated en = (ASN1Enumerated) obj; - buf.append(indent + "DER Enumerated(" + en.getValue() + ")" + nl); - } - else if (obj instanceof ASN1ObjectDescriptor) - { - ASN1ObjectDescriptor od = (ASN1ObjectDescriptor)obj; - buf.append(indent + "ObjectDescriptor(" + od.getBaseGraphicString().getString() + ") " + nl); - } - else if (obj instanceof ASN1External) - { - ASN1External ext = (ASN1External) obj; - buf.append(indent + "External " + nl); - String tab = indent + TAB; - if (ext.getDirectReference() != null) - { - buf.append(tab + "Direct Reference: " + ext.getDirectReference().getId() + nl); + } else if (obj instanceof ASN1IA5String) { + buf.appendIndentedLine(toASN1String("IA5String", (ASN1IA5String) obj)); + } else if (obj instanceof ASN1UTF8String) { + buf.appendIndentedLine(toASN1String("UTF8String", (ASN1UTF8String) obj)); + } else if (obj instanceof ASN1NumericString) { + buf.appendIndentedLine(toASN1String("NumericString", (ASN1NumericString) obj)); + } else if (obj instanceof ASN1PrintableString) { + buf.appendIndentedLine(toASN1String("PrintableString", (ASN1PrintableString) obj)); + } else if (obj instanceof ASN1VisibleString) { + buf.appendIndentedLine(toASN1String("VisibleString", (ASN1VisibleString) obj)); + } else if (obj instanceof ASN1BMPString) { + buf.appendIndentedLine(toASN1String("BMPString", (ASN1BMPString) obj)); + } else if (obj instanceof ASN1T61String) { + buf.appendIndentedLine(toASN1String("T61String", (ASN1T61String) obj)); + } else if (obj instanceof ASN1GraphicString) { + buf.appendIndentedLine(toASN1String("GraphicString", (ASN1GraphicString) obj)); + } else if (obj instanceof ASN1VideotexString) { + buf.appendIndentedLine(toASN1String("VideotexString", (ASN1VideotexString) obj)); + } else if (obj instanceof ASN1UTCTime) { + buf.appendIndentedLine(toASN1String("UTCTime", ((ASN1UTCTime) obj).getTime())); + } else if (obj instanceof ASN1GeneralizedTime) { + buf.appendIndentedLine(toASN1String("GeneralizedTime", ((ASN1GeneralizedTime) obj).getTime())); + } else if (obj instanceof ASN1Enumerated) { + final ASN1Enumerated en = (ASN1Enumerated) obj; + buf.appendIndentedLine(toASN1String("DER Enumerated", String.valueOf(en.getValue()))); + } else if (obj instanceof ASN1ObjectDescriptor) { + final ASN1ObjectDescriptor od = (ASN1ObjectDescriptor) obj; + buf.appendIndentedLine(toASN1String("ObjectDescriptor", od.getBaseGraphicString())); + } else if (obj instanceof ASN1External) { + final ASN1External ext = (ASN1External) obj; + buf.appendIndentedLine("External ") + .incrementIndentLevel(); + if (ext.getDirectReference() != null) { + buf.appendIndent().append("Direct Reference: ").appendLine(ext.getDirectReference().getId()); } - if (ext.getIndirectReference() != null) - { - buf.append(tab + "Indirect Reference: " + ext.getIndirectReference().toString() + nl); + if (ext.getIndirectReference() != null) { + buf.appendIndent().append("Indirect Reference: ").appendLine(String.valueOf(ext.getIndirectReference())); } - if (ext.getDataValueDescriptor() != null) - { - _dumpAsString(tab, verbose, ext.getDataValueDescriptor(), buf); + if (ext.getDataValueDescriptor() != null) { + _dumpAsString(verbose, ext.getDataValueDescriptor(), buf); } - buf.append(tab + "Encoding: " + ext.getEncoding() + nl); - _dumpAsString(tab, verbose, ext.getExternalContent(), buf); - } - else - { - buf.append(indent + obj.toString() + nl); + buf.appendIndent().append("Encoding: ").appendLine(String.valueOf(ext.getEncoding())); + _dumpAsString(verbose, ext.getExternalContent(), buf); + } else { + buf.appendIndentedLine(String.valueOf(obj)); } } + static String toASN1String(String asn1TypeName, ASN1String str) { + return toASN1String(asn1TypeName, str.getString()); + } + + static String toASN1String(String asn1TypeName, Object obj) { + return toASN1String(asn1TypeName, String.valueOf(obj)); + } + + static String toASN1String(String asn1TypeName, String str) { + return asn1TypeName + '(' + str + ')'; + } + + static String toASN1BitString(String asn1TypeName, ASN1BitString asn1BitString) { + return asn1TypeName + "[" + asn1BitString.getBytes().length + ", " + asn1BitString.getPadBits() + "] "; + } + /** * dump out a DER object as a formatted string, in non-verbose mode. * @@ -315,7 +204,7 @@ public static String dumpAsString( Object obj, boolean verbose) { - ASN1Primitive primitive; + final ASN1Primitive primitive; if (obj instanceof ASN1Primitive) { primitive = (ASN1Primitive)obj; @@ -329,58 +218,148 @@ else if (obj instanceof ASN1Encodable) return "unknown object type " + obj.toString(); } - StringBuffer buf = new StringBuffer(); - _dumpAsString("", verbose, primitive, buf); + final IndentingAppendable buf = new IndentingAppendable(); + _dumpAsString(verbose, primitive, buf); return buf.toString(); } - private static String dumpBinaryDataAsString(String indent, byte[] bytes) + private static void dumpBinaryDataAsString(IndentingAppendable buf, byte[] bytes) { - String nl = Strings.lineSeparator(); - StringBuffer buf = new StringBuffer(); - - indent += TAB; - - buf.append(nl); + buf.incrementIndentLevel().appendLine(); for (int i = 0; i < bytes.length; i += SAMPLE_SIZE) { + buf.appendIndent(); if (bytes.length - i > SAMPLE_SIZE) { - buf.append(indent); - buf.append(Strings.fromByteArray(Hex.encode(bytes, i, SAMPLE_SIZE))); - buf.append(TAB); - buf.append(calculateAscString(bytes, i, SAMPLE_SIZE)); - buf.append(nl); + buf.append(Strings.fromByteArray(Hex.encode(bytes, i, SAMPLE_SIZE))) + .appendIndentedLine(calculateAscString(bytes, i, SAMPLE_SIZE)); } else { - buf.append(indent); buf.append(Strings.fromByteArray(Hex.encode(bytes, i, bytes.length - i))); for (int j = bytes.length - i; j != SAMPLE_SIZE; j++) { buf.append(" "); } - buf.append(TAB); - buf.append(calculateAscString(bytes, i, bytes.length - i)); - buf.append(nl); + buf.appendIndentedLine(calculateAscString(bytes, i, bytes.length - i)); + } + } + buf.decrementIndentLevel(); + } + + private static String calculateAscString(byte[] bytes, int off, int len) { + final StringBuilder buf = new StringBuilder(len); + for (int i = off; i != off + len; i++) { + final byte b = bytes[i]; + if (b >= ' ' && b <= '~') { + buf.append((char) b); } } - return buf.toString(); } - private static String calculateAscString(byte[] bytes, int off, int len) - { - StringBuffer buf = new StringBuffer(); + static class IndentingAppendable implements Appendable { - for (int i = off; i != off + len; i++) - { - if (bytes[i] >= ' ' && bytes[i] <= '~') - { - buf.append((char)bytes[i]); + public static final String TAB = " "; + private static final String NL = System.lineSeparator(); + + private final String indentWith; + private final Appendable baseAppendable; + + private int indentLevel; + private String indent; + + public IndentingAppendable() { + this(new StringBuilder(), TAB); + } + + private IndentingAppendable(Appendable baseAppendable, String indentWith) { + this.baseAppendable = Objects.requireNonNull(baseAppendable, "base appendable"); + this.indentWith = Objects.requireNonNull(indentWith, "indent string"); + this.indent = indentWith; + } + + public IndentingAppendable incrementIndentLevel() { + this.indentLevel++; + this.indent = repeat(indentWith, indentLevel); + return this; + } + + public IndentingAppendable decrementIndentLevel() { + if (this.indentLevel > 0) + this.indentLevel--; + this.indent = repeat(indentWith, indentLevel); + return this; + } + + static String repeat(String base, int times) { + Objects.requireNonNull(base, "repeated string"); + if (times < 0) + throw new IllegalArgumentException("times is negative: " + times); + final int len = base.length(); + if (len == 1) + return base; + if (Integer.MAX_VALUE / times > len) + throw new OutOfMemoryError("Required length exceeds implementation limit"); + char[] toRepeat = base.toCharArray(); + char[] repeated = new char[len * times]; + final int strLen = base.length(); + for (int i = 0; i < times - 1; i++) { + final int from = i * strLen; + System.arraycopy(toRepeat, 0, repeated, from, strLen); } + return new String(repeated).intern(); } - return buf.toString(); + @Override + public IndentingAppendable append(CharSequence csq) { + try { + baseAppendable.append(csq); + return this; + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + @Override + public IndentingAppendable append(CharSequence csq, int start, int end) { + try { + baseAppendable.append(csq, start, end); + return this; + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + @Override + public IndentingAppendable append(char c) { + try { + baseAppendable.append(c); + return this; + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + public IndentingAppendable appendIndent() { + return append(indent); + } + + public IndentingAppendable appendLine(CharSequence csq) { + return append(csq).appendLine(); + } + + public IndentingAppendable appendLine() { + return append(NL); + } + + public IndentingAppendable appendIndentedLine(CharSequence csq) { + return appendIndent().appendLine(csq); + } + + @Override + public String toString() { + return baseAppendable.toString(); + } } } diff --git a/core/src/main/java/org/bouncycastle/asn1/util/DERDump.java b/core/src/main/java/org/bouncycastle/asn1/util/DERDump.java index 372009fe6c..072028ffd6 100644 --- a/core/src/main/java/org/bouncycastle/asn1/util/DERDump.java +++ b/core/src/main/java/org/bouncycastle/asn1/util/DERDump.java @@ -17,9 +17,9 @@ public class DERDump public static String dumpAsString( ASN1Primitive obj) { - StringBuffer buf = new StringBuffer(); + final IndentingAppendable buf = new IndentingAppendable(); - _dumpAsString("", false, obj, buf); + _dumpAsString(false, obj, buf); return buf.toString(); } diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/CRLDistPoint.java b/core/src/main/java/org/bouncycastle/asn1/x509/CRLDistPoint.java index 1aa3f38d04..b2554b3e0b 100644 --- a/core/src/main/java/org/bouncycastle/asn1/x509/CRLDistPoint.java +++ b/core/src/main/java/org/bouncycastle/asn1/x509/CRLDistPoint.java @@ -81,17 +81,14 @@ public ASN1Primitive toASN1Primitive() public String toString() { - StringBuffer buf = new StringBuffer(); - String sep = Strings.lineSeparator(); + final StringBuilder buf = new StringBuilder(); + final String nl = Strings.lineSeparator(); - buf.append("CRLDistPoint:"); - buf.append(sep); - DistributionPoint dp[] = getDistributionPoints(); - for (int i = 0; i != dp.length; i++) + buf.append("CRLDistPoint:").append(nl); + + for (DistributionPoint dp : getDistributionPoints()) { - buf.append(" "); - buf.append(dp[i]); - buf.append(sep); + buf.append(" ").append(dp).append(nl); } return buf.toString(); } diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/CertificatePolicies.java b/core/src/main/java/org/bouncycastle/asn1/x509/CertificatePolicies.java index 5b4385a24f..3c5cb393f0 100644 --- a/core/src/main/java/org/bouncycastle/asn1/x509/CertificatePolicies.java +++ b/core/src/main/java/org/bouncycastle/asn1/x509/CertificatePolicies.java @@ -7,6 +7,8 @@ import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERSequence; +import java.util.StringJoiner; + public class CertificatePolicies extends ASN1Object { @@ -112,16 +114,12 @@ public ASN1Primitive toASN1Primitive() public String toString() { - StringBuffer p = new StringBuffer(); - for (int i = 0; i < policyInformation.length; i++) + final StringJoiner joiner = new StringJoiner(", ", "[", "]"); + for (PolicyInformation p : policyInformation) { - if (p.length() != 0) - { - p.append(", "); - } - p.append(policyInformation[i]); + joiner.add(String.valueOf(p)); } - return "CertificatePolicies: [" + p + "]"; + return "CertificatePolicies: " + joiner; } } diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/GeneralName.java b/core/src/main/java/org/bouncycastle/asn1/x509/GeneralName.java index 20c19100e4..6b1154da1e 100644 --- a/core/src/main/java/org/bouncycastle/asn1/x509/GeneralName.java +++ b/core/src/main/java/org/bouncycastle/asn1/x509/GeneralName.java @@ -248,7 +248,7 @@ public ASN1Encodable getName() public String toString() { - StringBuffer buf = new StringBuffer(); + final StringBuilder buf = new StringBuilder(); buf.append(tag); buf.append(": "); @@ -260,10 +260,10 @@ public String toString() buf.append(ASN1IA5String.getInstance(obj).getString()); break; case directoryName: - buf.append(X500Name.getInstance(obj).toString()); + buf.append(X500Name.getInstance(obj)); break; default: - buf.append(obj.toString()); + buf.append(obj); } return buf.toString(); } diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/GeneralNames.java b/core/src/main/java/org/bouncycastle/asn1/x509/GeneralNames.java index 5ba472bf84..836ab12ffd 100644 --- a/core/src/main/java/org/bouncycastle/asn1/x509/GeneralNames.java +++ b/core/src/main/java/org/bouncycastle/asn1/x509/GeneralNames.java @@ -95,17 +95,14 @@ public ASN1Primitive toASN1Primitive() public String toString() { - StringBuffer buf = new StringBuffer(); - String sep = Strings.lineSeparator(); + final StringBuilder buf = new StringBuilder(); + final String nl = Strings.lineSeparator(); - buf.append("GeneralNames:"); - buf.append(sep); + buf.append("GeneralNames:").append(nl); - for (int i = 0; i != names.length; i++) + for (GeneralName name : names) { - buf.append(" "); - buf.append(names[i]); - buf.append(sep); + buf.append(" ").append(name).append(nl); } return buf.toString(); } diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/PolicyInformation.java b/core/src/main/java/org/bouncycastle/asn1/x509/PolicyInformation.java index 3b584a8b60..b7d4904b32 100644 --- a/core/src/main/java/org/bouncycastle/asn1/x509/PolicyInformation.java +++ b/core/src/main/java/org/bouncycastle/asn1/x509/PolicyInformation.java @@ -1,11 +1,8 @@ package org.bouncycastle.asn1.x509; -import org.bouncycastle.asn1.ASN1EncodableVector; -import org.bouncycastle.asn1.ASN1Object; -import org.bouncycastle.asn1.ASN1ObjectIdentifier; -import org.bouncycastle.asn1.ASN1Primitive; -import org.bouncycastle.asn1.ASN1Sequence; -import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.*; + +import java.util.StringJoiner; public class PolicyInformation extends ASN1Object @@ -89,26 +86,19 @@ public ASN1Primitive toASN1Primitive() public String toString() { - StringBuffer sb = new StringBuffer(); + final StringBuilder sb = new StringBuilder(); sb.append("Policy information: "); sb.append(policyIdentifier); if (policyQualifiers != null) { - StringBuffer p = new StringBuffer(); - for (int i = 0; i < policyQualifiers.size(); i++) + final StringJoiner joiner = new StringJoiner(", ", "[", "]"); + for (ASN1Encodable element : policyQualifiers) { - if (p.length() != 0) - { - p.append(", "); - } - p.append(PolicyQualifierInfo.getInstance(policyQualifiers.getObjectAt(i))); + joiner.add(String.valueOf(element)); } - - sb.append("["); - sb.append(p); - sb.append("]"); + sb.append(joiner); } return sb.toString(); diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/RoleSyntax.java b/core/src/main/java/org/bouncycastle/asn1/x509/RoleSyntax.java index d6926bddd5..f7f49de918 100644 --- a/core/src/main/java/org/bouncycastle/asn1/x509/RoleSyntax.java +++ b/core/src/main/java/org/bouncycastle/asn1/x509/RoleSyntax.java @@ -216,15 +216,17 @@ public ASN1Primitive toASN1Primitive() public String toString() { - StringBuffer buff = new StringBuffer("Name: " + this.getRoleNameAsString() + - " - Auth: "); + final StringBuilder buff = new StringBuilder("Name: ") + .append(this.getRoleNameAsString()) + .append(" - Auth: "); + if(this.roleAuthority == null || roleAuthority.getNames().length == 0) { buff.append("N/A"); } else { - String[] names = this.getRoleAuthorityAsString(); + final String[] names = this.getRoleAuthorityAsString(); buff.append('[').append(names[0]); for(int i = 1; i < names.length; i++) { diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/CramerShoupCiphertext.java b/core/src/main/java/org/bouncycastle/crypto/engines/CramerShoupCiphertext.java index edf1bd23ac..a2101873dc 100644 --- a/core/src/main/java/org/bouncycastle/crypto/engines/CramerShoupCiphertext.java +++ b/core/src/main/java/org/bouncycastle/crypto/engines/CramerShoupCiphertext.java @@ -96,14 +96,7 @@ public void setV(BigInteger v) public String toString() { - StringBuffer result = new StringBuffer(); - - result.append("u1: " + u1.toString()); - result.append("\nu2: " + u2.toString()); - result.append("\ne: " + e.toString()); - result.append("\nv: " + v.toString()); - - return result.toString(); + return "u1: " + u1 + "\nu2: " + u2 + "\ne: " + e + "\nv: " + v; } /** diff --git a/core/src/main/java/org/bouncycastle/i18n/LocalizedMessage.java b/core/src/main/java/org/bouncycastle/i18n/LocalizedMessage.java index ac75c6c345..5993f55944 100644 --- a/core/src/main/java/org/bouncycastle/i18n/LocalizedMessage.java +++ b/core/src/main/java/org/bouncycastle/i18n/LocalizedMessage.java @@ -460,13 +460,14 @@ public void setFilter(Filter filter) public String toString() { - StringBuffer sb = new StringBuffer(); + final StringBuilder sb = new StringBuilder(); sb.append("Resource: \"").append(resource); - sb.append("\" Id: \"").append(id).append("\""); + sb.append("\" Id: \"").append(id).append('"'); sb.append(" Arguments: ").append(arguments.getArguments().length).append(" normal"); - if (extraArgs != null && extraArgs.getArguments().length > 0) + if (extraArgs != null) { - sb.append(", ").append(extraArgs.getArguments().length).append(" extra"); + final int extraLen = extraArgs.getArguments().length; + if (extraLen > 0) sb.append(", ").append(extraLen).append(" extra"); } sb.append(" Encoding: ").append(encoding); sb.append(" ClassLoader: ").append(loader); diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/crystals/dilithium/Poly.java b/core/src/main/java/org/bouncycastle/pqc/crypto/crystals/dilithium/Poly.java index 62d6a753ce..76be68ac76 100644 --- a/core/src/main/java/org/bouncycastle/pqc/crypto/crystals/dilithium/Poly.java +++ b/core/src/main/java/org/bouncycastle/pqc/crypto/crystals/dilithium/Poly.java @@ -2,6 +2,8 @@ import org.bouncycastle.crypto.digests.SHAKEDigest; +import java.util.StringJoiner; + class Poly { private final int polyUniformNBlocks; @@ -786,17 +788,10 @@ public void shiftLeft() public String toString() { - StringBuffer out = new StringBuffer(); - out.append("["); - for (int i = 0; i < coeffs.length; i++) - { - out.append(coeffs[i]); - if (i != coeffs.length - 1) - { - out.append(", "); - } + final StringJoiner out = new StringJoiner(", ", "[", "]"); + for (int c : coeffs){ + out.add(String.valueOf(c)); } - out.append("]"); return out.toString(); } } diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/mlkem/Poly.java b/core/src/main/java/org/bouncycastle/pqc/crypto/mlkem/Poly.java index d7402a5ea7..07d6c75b2d 100644 --- a/core/src/main/java/org/bouncycastle/pqc/crypto/mlkem/Poly.java +++ b/core/src/main/java/org/bouncycastle/pqc/crypto/mlkem/Poly.java @@ -1,5 +1,9 @@ package org.bouncycastle.pqc.crypto.mlkem; +import java.util.StringJoiner; + +import java.util.StringJoiner; + class Poly { private short[] coeffs; @@ -337,17 +341,10 @@ public void polySubtract(Poly b) public String toString() { - StringBuffer out = new StringBuffer(); - out.append("["); - for (int i = 0; i < coeffs.length; i++) - { - out.append(coeffs[i]); - if (i != coeffs.length - 1) - { - out.append(", "); - } + final StringJoiner out = new StringJoiner(", ", "[", "]"); + for (short c : coeffs){ + out.add(String.valueOf(c)); } - out.append("]"); return out.toString(); } } diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/mlkem/PolyVec.java b/core/src/main/java/org/bouncycastle/pqc/crypto/mlkem/PolyVec.java index d6613e904f..ef17b10f72 100644 --- a/core/src/main/java/org/bouncycastle/pqc/crypto/mlkem/PolyVec.java +++ b/core/src/main/java/org/bouncycastle/pqc/crypto/mlkem/PolyVec.java @@ -2,6 +2,8 @@ import org.bouncycastle.util.Arrays; +import java.util.StringJoiner; + class PolyVec { Poly[] vec; @@ -256,17 +258,11 @@ public void conditionalSubQ() public String toString() { - StringBuffer out = new StringBuffer(); - out.append("["); + final StringJoiner out = new StringJoiner(", ", "[", "]"); for (int i = 0; i < kyberK; i++) { - out.append(vec[i].toString()); - if (i != kyberK - 1) - { - out.append(", "); - } + out.add(vec[i].toString()); } - out.append("]"); return out.toString(); } } diff --git a/core/src/main/java/org/bouncycastle/pqc/legacy/math/linearalgebra/GF2Vector.java b/core/src/main/java/org/bouncycastle/pqc/legacy/math/linearalgebra/GF2Vector.java index b0fa762acd..bf34951578 100644 --- a/core/src/main/java/org/bouncycastle/pqc/legacy/math/linearalgebra/GF2Vector.java +++ b/core/src/main/java/org/bouncycastle/pqc/legacy/math/linearalgebra/GF2Vector.java @@ -516,24 +516,17 @@ public int hashCode() */ public String toString() { - StringBuffer buf = new StringBuffer(); + final StringBuilder buf = new StringBuilder(); for (int i = 0; i < length; i++) { if ((i != 0) && ((i & 0x1f) == 0)) { buf.append(' '); } - int q = i >> 5; - int r = i & 0x1f; - int bit = v[q] & (1 << r); - if (bit == 0) - { - buf.append('0'); - } - else - { - buf.append('1'); - } + final int q = i >> 5; + final int r = i & 0x1f; + final int bit = v[q] & (1 << r); + buf.append(bit == 0 ? '0' : '1'); } return buf.toString(); } diff --git a/core/src/main/java/org/bouncycastle/pqc/legacy/math/linearalgebra/GF2mVector.java b/core/src/main/java/org/bouncycastle/pqc/legacy/math/linearalgebra/GF2mVector.java index 73f4192b4a..f5edd91593 100644 --- a/core/src/main/java/org/bouncycastle/pqc/legacy/math/linearalgebra/GF2mVector.java +++ b/core/src/main/java/org/bouncycastle/pqc/legacy/math/linearalgebra/GF2mVector.java @@ -233,22 +233,13 @@ public int hashCode() */ public String toString() { - StringBuffer buf = new StringBuffer(); - for (int i = 0; i < vector.length; i++) - { - for (int j = 0; j < field.getDegree(); j++) - { - int r = j & 0x1f; - int bitMask = 1 << r; - int coeff = vector[i] & bitMask; - if (coeff != 0) - { - buf.append('1'); - } - else - { - buf.append('0'); - } + final StringBuilder buf = new StringBuilder(Math.max(vector.length, 16)); + for (int k : vector) { + for (int j = 0; j < field.getDegree(); j++) { + final int r = j & 0x1f; + final int bitMask = 1 << r; + final int coeff = k & bitMask; + buf.append(coeff == 0 ? '0' : '1'); } buf.append(' '); } diff --git a/core/src/main/java/org/bouncycastle/util/Fingerprint.java b/core/src/main/java/org/bouncycastle/util/Fingerprint.java index 7027d4948c..78314b4ea5 100644 --- a/core/src/main/java/org/bouncycastle/util/Fingerprint.java +++ b/core/src/main/java/org/bouncycastle/util/Fingerprint.java @@ -3,6 +3,8 @@ import org.bouncycastle.crypto.digests.SHA512tDigest; import org.bouncycastle.crypto.digests.SHAKEDigest; +import java.util.StringJoiner; + /** * Basic 20 byte finger print class. */ @@ -64,18 +66,18 @@ public byte[] getFingerprint() public String toString() { - StringBuffer sb = new StringBuffer(); - for (int i = 0; i != fingerprint.length; i++) + final StringBuilder sb = new StringBuilder(); + for (byte b : fingerprint) { - if (i > 0) - { - sb.append(":"); - } - sb.append(encodingTable[(fingerprint[i] >>> 4) & 0xf]); - sb.append(encodingTable[fingerprint[i] & 0x0f]); + sb.append(encodingTable[(b >>> 4) & 0xf]); + sb.append(encodingTable[b & 0x0f]); + // always add the separator, eventually substring + // to remove the last char after finishing (help branch prediction avoiding checks in the loop) + sb.append(':'); } - return sb.toString(); + final int len = sb.length(); + return len == 0 ? "" : sb.substring(0, len - 1); } public boolean equals(Object o) diff --git a/core/src/test/java/org/bouncycastle/test/TestResourceFinder.java b/core/src/test/java/org/bouncycastle/test/TestResourceFinder.java index 14214bafae..19e8a775b2 100644 --- a/core/src/test/java/org/bouncycastle/test/TestResourceFinder.java +++ b/core/src/test/java/org/bouncycastle/test/TestResourceFinder.java @@ -12,28 +12,29 @@ public class TestResourceFinder /** * We search starting at the working directory looking for the bc-test-data directory. * - * @throws FileNotFoundException + * @throws FileNotFoundException in case the test data directory is missing */ public static InputStream findTestResource(String homeDir, String fileName) throws FileNotFoundException { String wrkDirName = System.getProperty("user.dir"); - String separator = System.getProperty("file.separator"); File wrkDir = new File(wrkDirName); File dataDir = new File(wrkDir, dataDirName); - while (!dataDir.exists() && wrkDirName.length() > 1) + while (!dataDir.exists()) { - wrkDirName = wrkDirName.substring(0, wrkDirName.lastIndexOf(separator)); + wrkDirName = wrkDir.getParent(); + if (wrkDirName == null) break; wrkDir = new File(wrkDirName); dataDir = new File(wrkDir, dataDirName); } if (!dataDir.exists()) { - String ln = System.getProperty("line.separator"); + final String ln = System.getProperty("line.separator"); throw new FileNotFoundException("Test data directory " + dataDirName + " not found." + ln + "Test data available from: https://github.com/bcgit/bc-test-data.git"); } - return new FileInputStream(new File(dataDir, homeDir + separator + fileName)); + final File homeDirFile = new File(dataDir, homeDir); + return new FileInputStream(new File(homeDirFile, fileName)); } }