From aa68d56fa203b3a439cbf733678d7d0e8cb79dbd Mon Sep 17 00:00:00 2001 From: mormao Date: Tue, 23 Jul 2024 16:14:57 +0200 Subject: [PATCH 01/45] avoid using StringBuffer, as they are synchronized, in favour of StringBuilder / StringJoiner / string-composition --- .../pqc/crypto/crystals/kyber/Poly.java | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/crystals/kyber/Poly.java b/core/src/main/java/org/bouncycastle/pqc/crypto/crystals/kyber/Poly.java index 7d9b9a2f54..02be4c977c 100644 --- a/core/src/main/java/org/bouncycastle/pqc/crypto/crystals/kyber/Poly.java +++ b/core/src/main/java/org/bouncycastle/pqc/crypto/crystals/kyber/Poly.java @@ -1,5 +1,7 @@ package org.bouncycastle.pqc.crypto.crystals.kyber; +import java.util.StringJoiner; + class Poly { private short[] coeffs; @@ -337,17 +339,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(); } } From a4fdd3e340f89715d5b8e14fc002075dd8f12765 Mon Sep 17 00:00:00 2001 From: mormao Date: Tue, 23 Jul 2024 16:15:06 +0200 Subject: [PATCH 02/45] avoid using StringBuffer, as they are synchronized, in favour of StringBuilder / StringJoiner / string-composition --- .../legacy/math/linearalgebra/GF2mVector.java | 23 ++++++------------- 1 file changed, 7 insertions(+), 16 deletions(-) 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(' '); } From 57240c359e497ac3bd58ae437586a240e97375e6 Mon Sep 17 00:00:00 2001 From: mormao Date: Tue, 23 Jul 2024 16:25:45 +0200 Subject: [PATCH 03/45] avoid using StringBuffer, as they are synchronized, in favour of StringBuilder / StringJoiner / string-composition --- .../pqc/crypto/crystals/kyber/PolyVec.java | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/crystals/kyber/PolyVec.java b/core/src/main/java/org/bouncycastle/pqc/crypto/crystals/kyber/PolyVec.java index e1ca688a73..588bbb4233 100644 --- a/core/src/main/java/org/bouncycastle/pqc/crypto/crystals/kyber/PolyVec.java +++ b/core/src/main/java/org/bouncycastle/pqc/crypto/crystals/kyber/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(); } } From c9d723af0868269a523c5cb7e21c542d92bdaa6a Mon Sep 17 00:00:00 2001 From: mormao Date: Tue, 23 Jul 2024 16:30:18 +0200 Subject: [PATCH 04/45] avoid using StringBuffer, as they are synchronized, in favour of StringBuilder / StringJoiner / string-composition. Make loop variables "final" to leverage compiler bytecode inlining --- .../legacy/math/linearalgebra/GF2Vector.java | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) 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(); } From 89d82c09142d3780a561fbff986bd0797da1c16e Mon Sep 17 00:00:00 2001 From: mormao Date: Tue, 23 Jul 2024 16:33:05 +0200 Subject: [PATCH 05/45] avoid using StringBuffer, as they are synchronized, in favour of StringBuilder / StringJoiner / string-composition. Make loop variables "final" to leverage compiler bytecode inlining --- .../pqc/crypto/crystals/dilithium/Poly.java | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) 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(); } } From 7353e588e6ef2ff0d4dede2ced8d2efa8888cb4f Mon Sep 17 00:00:00 2001 From: mormao Date: Tue, 23 Jul 2024 16:34:55 +0200 Subject: [PATCH 06/45] avoid using StringBuffer, as they are synchronized, in favour of StringBuilder / StringJoiner / string-composition. --- .../main/java/org/bouncycastle/asn1/x509/GeneralName.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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(); } From bf8b360d3598a0b3b1f0c3909941b8bee250e5d2 Mon Sep 17 00:00:00 2001 From: mormao Date: Tue, 23 Jul 2024 16:40:40 +0200 Subject: [PATCH 07/45] avoid using StringBuffer, as they are synchronized, in favour of StringJoiner with prefix "[", suffix "]" and separator ", " --- .../asn1/x509/CertificatePolicies.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) 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; } } From a829af52bce65acbbea117e1c75ccdcdd533a3f6 Mon Sep 17 00:00:00 2001 From: mormao Date: Tue, 23 Jul 2024 16:46:12 +0200 Subject: [PATCH 08/45] Replaced StringBuffer (which is synchronized) with StringBuilder --- .../org/bouncycastle/asn1/x509/CRLDistPoint.java | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) 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(); } From fb31e8cae32b0bfe98205a174364fbc375644c5f Mon Sep 17 00:00:00 2001 From: mormao Date: Tue, 23 Jul 2024 16:53:31 +0200 Subject: [PATCH 09/45] Replaced StringBuffer with StringBuilder and possibly joining elements of an iterable with a StringJoiner --- .../asn1/x509/PolicyInformation.java | 26 ++++++------------- 1 file changed, 8 insertions(+), 18 deletions(-) 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(); From e2923c64e1164fe198a3e11dae6c0cb17cfc5d43 Mon Sep 17 00:00:00 2001 From: mormao Date: Tue, 23 Jul 2024 16:55:50 +0200 Subject: [PATCH 10/45] Replaced StringBuffer with a StringBuilder to avoid synchronization --- .../org/bouncycastle/asn1/x509/GeneralNames.java | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) 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(); } From 7d2f662c9baedc5822450994a0f3d73df840d1bb Mon Sep 17 00:00:00 2001 From: mormao Date: Tue, 23 Jul 2024 16:58:57 +0200 Subject: [PATCH 11/45] Replaced StringBuffer with a StringBuilder to avoid synchronization --- .../main/java/org/bouncycastle/asn1/x509/RoleSyntax.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) 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++) { From b65e70d4924be7c0dd0406df52ffc4543edfb860 Mon Sep 17 00:00:00 2001 From: mormao Date: Tue, 23 Jul 2024 17:09:55 +0200 Subject: [PATCH 12/45] Replaced StringBuffer with a StringBuilder to avoid synchronization --- .../org/bouncycastle/util/Fingerprint.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/org/bouncycastle/util/Fingerprint.java b/core/src/main/java/org/bouncycastle/util/Fingerprint.java index 7027d4948c..4c09530d5b 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,16 @@ 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]); + sb.append(':'); // eventually remove the last char after finishing (help branch prediction) } - return sb.toString(); + final int len = sb.length(); + return len == 0 ? "" : sb.deleteCharAt(len - 1).toString(); } public boolean equals(Object o) From 795cca5d9e7cd4367dd71bfa136cf6a7dc125c66 Mon Sep 17 00:00:00 2001 From: mormao Date: Tue, 23 Jul 2024 17:13:09 +0200 Subject: [PATCH 13/45] Replaced StringBuffer with a StringBuilder to avoid synchronization --- core/src/main/java/org/bouncycastle/util/Fingerprint.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/bouncycastle/util/Fingerprint.java b/core/src/main/java/org/bouncycastle/util/Fingerprint.java index 4c09530d5b..78314b4ea5 100644 --- a/core/src/main/java/org/bouncycastle/util/Fingerprint.java +++ b/core/src/main/java/org/bouncycastle/util/Fingerprint.java @@ -71,11 +71,13 @@ public String toString() { sb.append(encodingTable[(b >>> 4) & 0xf]); sb.append(encodingTable[b & 0x0f]); - sb.append(':'); // eventually remove the last char after finishing (help branch prediction) + // always add the separator, eventually substring + // to remove the last char after finishing (help branch prediction avoiding checks in the loop) + sb.append(':'); } final int len = sb.length(); - return len == 0 ? "" : sb.deleteCharAt(len - 1).toString(); + return len == 0 ? "" : sb.substring(0, len - 1); } public boolean equals(Object o) From b7cd6bc5948de436aab62ab6a17f9d8f4ecb2246 Mon Sep 17 00:00:00 2001 From: mormao Date: Tue, 23 Jul 2024 17:17:54 +0200 Subject: [PATCH 14/45] Replaced StringBuffer with a String composition (simpler, faster and null-safe) --- .../crypto/engines/CramerShoupCiphertext.java | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) 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; } /** From cee74fbdf831281b490afca10593ca135e638836 Mon Sep 17 00:00:00 2001 From: mormao Date: Tue, 23 Jul 2024 17:24:00 +0200 Subject: [PATCH 15/45] Replaced StringBuffer with a StringBuilder --- .../java/org/bouncycastle/i18n/LocalizedMessage.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) 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); From b9237887c2a1124d199f10165d563fb585fe1196 Mon Sep 17 00:00:00 2001 From: mormao Date: Tue, 23 Jul 2024 17:34:23 +0200 Subject: [PATCH 16/45] Replaced StringBuffer with a StringBuilder to avoid synchronization --- .../main/java/org/bouncycastle/asn1/ASN1BitString.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) 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]); } From 0989e64685ec5b3791502b388e86413e02a22062 Mon Sep 17 00:00:00 2001 From: mormao Date: Tue, 23 Jul 2024 17:35:13 +0200 Subject: [PATCH 17/45] Replaced StringBuffer with a StringBuilder to avoid synchronization --- core/src/main/java/org/bouncycastle/asn1/ASN1RelativeOID.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/bouncycastle/asn1/ASN1RelativeOID.java b/core/src/main/java/org/bouncycastle/asn1/ASN1RelativeOID.java index aa75ace012..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) { - StringBuffer objId = new StringBuffer(); + final StringBuilder objId = new StringBuilder(); long value = 0; BigInteger bigValue = null; boolean first = true; From 0034cf45f7d8ab72c16bbca4046768dbea949cb2 Mon Sep 17 00:00:00 2001 From: mormao Date: Wed, 24 Jul 2024 14:02:33 +0200 Subject: [PATCH 18/45] Replaced StringBuffer with a StringBuilder to avoid synchronization via a new context-aware Appendable --- .../org/bouncycastle/asn1/util/ASN1Dump.java | 546 +++++++++--------- .../org/bouncycastle/asn1/util/DERDump.java | 4 +- 2 files changed, 271 insertions(+), 279 deletions(-) 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..dedeec313d 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,20 @@ 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 String TAB = IndentingAppendable.TAB; private static final int SAMPLE_SIZE = 32; /** @@ -53,245 +23,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"); + 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"; } - else - { - buf.append("Set"); - } - buf.append(nl); - - ASN1Set set = (ASN1Set)obj; - String elementsIndent = indent + TAB; + buf.appendIndentedLine(description); - 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 + "] "); + 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 + "]"); } - else - { - buf.append(indent + "DER Octet String" + "[" + oct.getOctets().length + "] "); - } - if (verbose) - { - buf.append(dumpBinaryDataAsString(indent, oct.getOctets())); - } - else - { - buf.append(nl); - } - } - 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(); - - if (bitString instanceof DERBitString) - { - buf.append(indent + "DER Bit String" + "[" + bytes.length + ", " + padBits + "] "); + if (verbose) { + dumpBinaryDataAsString(buf, oct.getOctets()); + } else { + buf.append(NL); } - else if (bitString instanceof DLBitString) - { - buf.append(indent + "DL Bit String" + "[" + bytes.length + ", " + padBits + "] "); - } - else - { - buf.append(indent + "BER Bit String" + "[" + bytes.length + ", " + padBits + "] "); + } 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); } + buf.appendIndentedLine(line); - if (verbose) - { - buf.append(dumpBinaryDataAsString(indent, bytes)); - } - else - { - buf.append(nl); + if (verbose) { + dumpBinaryDataAsString(buf, bitString.getBytes()); + } else { + buf.appendLine(); } - } - 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 +205,7 @@ public static String dumpAsString( Object obj, boolean verbose) { - ASN1Primitive primitive; + final ASN1Primitive primitive; if (obj instanceof ASN1Primitive) { primitive = (ASN1Primitive)obj; @@ -329,58 +219,160 @@ 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); + } + + public IndentingAppendable(String indentWith) { + this(new StringBuilder(), indentWith); + } + + public IndentingAppendable(Appendable baseAppendable) { + this(baseAppendable, 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; + } + + public int getIndentLevel(){ + return indentLevel; + } + + 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(); } From 9bcc8ac5dbb1575bf2e470d439ab9a84122e8223 Mon Sep 17 00:00:00 2001 From: mormao Date: Wed, 24 Jul 2024 14:21:41 +0200 Subject: [PATCH 19/45] Traverse the file system using java.io.File::getParent instead of substring by System's file separator, as it can lead to StringIndexOutOfBoundException in case the test folder does not exist --- .../org/bouncycastle/test/TestResourceFinder.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/core/src/test/java/org/bouncycastle/test/TestResourceFinder.java b/core/src/test/java/org/bouncycastle/test/TestResourceFinder.java index 14214bafae..b0892a9955 100644 --- a/core/src/test/java/org/bouncycastle/test/TestResourceFinder.java +++ b/core/src/test/java/org/bouncycastle/test/TestResourceFinder.java @@ -18,22 +18,23 @@ 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)); } } From a73eb35ef5ddf5bd47683d7f97035ec4b75c19fb Mon Sep 17 00:00:00 2001 From: mormao Date: Wed, 24 Jul 2024 14:25:05 +0200 Subject: [PATCH 20/45] Traverse the file system using java.io.File::getParent instead of substring by System's file separator, as it can lead to StringIndexOutOfBoundException in case the test folder does not exist --- .../src/test/java/org/bouncycastle/test/TestResourceFinder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/test/java/org/bouncycastle/test/TestResourceFinder.java b/core/src/test/java/org/bouncycastle/test/TestResourceFinder.java index b0892a9955..19e8a775b2 100644 --- a/core/src/test/java/org/bouncycastle/test/TestResourceFinder.java +++ b/core/src/test/java/org/bouncycastle/test/TestResourceFinder.java @@ -12,7 +12,7 @@ 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 From 404a4779cb8cbc5c3b46d0d8d12926433310047c Mon Sep 17 00:00:00 2001 From: mormao Date: Wed, 24 Jul 2024 14:25:23 +0200 Subject: [PATCH 21/45] Deleted unused methods --- .../java/org/bouncycastle/asn1/util/ASN1Dump.java | 13 ------------- 1 file changed, 13 deletions(-) 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 dedeec313d..b40ff7c363 100644 --- a/core/src/main/java/org/bouncycastle/asn1/util/ASN1Dump.java +++ b/core/src/main/java/org/bouncycastle/asn1/util/ASN1Dump.java @@ -14,7 +14,6 @@ public class ASN1Dump { private static final String NL = System.lineSeparator(); - private static final String TAB = IndentingAppendable.TAB; private static final int SAMPLE_SIZE = 32; /** @@ -274,14 +273,6 @@ public IndentingAppendable() { this(new StringBuilder(), TAB); } - public IndentingAppendable(String indentWith) { - this(new StringBuilder(), indentWith); - } - - public IndentingAppendable(Appendable baseAppendable) { - this(baseAppendable, TAB); - } - private IndentingAppendable(Appendable baseAppendable, String indentWith) { this.baseAppendable = Objects.requireNonNull(baseAppendable, "base appendable"); this.indentWith = Objects.requireNonNull(indentWith, "indent string"); @@ -301,10 +292,6 @@ public IndentingAppendable decrementIndentLevel() { return this; } - public int getIndentLevel(){ - return indentLevel; - } - static String repeat(String base, int times) { Objects.requireNonNull(base, "repeated string"); if (times < 0) From 6cbd95ae4fe53baee233acddd36698463cd3043c Mon Sep 17 00:00:00 2001 From: Marco Moriggi <16181266+stratozero@users.noreply.github.com> Date: Wed, 24 Jul 2024 15:39:46 +0200 Subject: [PATCH 22/45] Update codeql.yml Correct bad syntax --- .github/workflows/codeql.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index a4c720847e..a9172ad97f 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -66,7 +66,7 @@ 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: | + - run: | echo "Run, Build Application using script" gradle clean build From e6e945263982f08d737e82dfe92d7a8594b7868a Mon Sep 17 00:00:00 2001 From: mormao Date: Mon, 29 Jul 2024 09:10:10 +0200 Subject: [PATCH 23/45] test-created files removed from version control --- .gitignore | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) 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 From 3812e3b951179160bc15e168c893eb8399306db1 Mon Sep 17 00:00:00 2001 From: mormao Date: Tue, 23 Jul 2024 16:14:57 +0200 Subject: [PATCH 24/45] avoid using StringBuffer, as they are synchronized, in favour of StringBuilder / StringJoiner / string-composition --- .../org/bouncycastle/pqc/crypto/mlkem/Poly.java | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) 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..c0e1ab48a4 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,7 @@ package org.bouncycastle.pqc.crypto.mlkem; +import java.util.StringJoiner; + class Poly { private short[] coeffs; @@ -337,17 +339,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(); } } From c684e5745660ec6937fda5efe9b45d0cc140322d Mon Sep 17 00:00:00 2001 From: mormao Date: Tue, 23 Jul 2024 16:15:06 +0200 Subject: [PATCH 25/45] avoid using StringBuffer, as they are synchronized, in favour of StringBuilder / StringJoiner / string-composition --- .../legacy/math/linearalgebra/GF2mVector.java | 23 ++++++------------- 1 file changed, 7 insertions(+), 16 deletions(-) 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(' '); } From 3c4a48cfa52890ec2284119e0fb33e56c176efd2 Mon Sep 17 00:00:00 2001 From: mormao Date: Tue, 23 Jul 2024 16:25:45 +0200 Subject: [PATCH 26/45] avoid using StringBuffer, as they are synchronized, in favour of StringBuilder / StringJoiner / string-composition --- .../org/bouncycastle/pqc/crypto/mlkem/PolyVec.java | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) 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(); } } From eb02e3d9b975db5d8742657b3b0dd21f419aacdd Mon Sep 17 00:00:00 2001 From: mormao Date: Tue, 23 Jul 2024 16:30:18 +0200 Subject: [PATCH 27/45] avoid using StringBuffer, as they are synchronized, in favour of StringBuilder / StringJoiner / string-composition. Make loop variables "final" to leverage compiler bytecode inlining --- .../legacy/math/linearalgebra/GF2Vector.java | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) 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(); } From f940d6a5553e0cf7e035e498ad28f0cc5c4edca1 Mon Sep 17 00:00:00 2001 From: mormao Date: Tue, 23 Jul 2024 16:33:05 +0200 Subject: [PATCH 28/45] avoid using StringBuffer, as they are synchronized, in favour of StringBuilder / StringJoiner / string-composition. Make loop variables "final" to leverage compiler bytecode inlining --- .../pqc/crypto/crystals/dilithium/Poly.java | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) 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(); } } From 3a847efbb9d1aa8dc1667af610d57581fd65b282 Mon Sep 17 00:00:00 2001 From: mormao Date: Tue, 23 Jul 2024 16:34:55 +0200 Subject: [PATCH 29/45] avoid using StringBuffer, as they are synchronized, in favour of StringBuilder / StringJoiner / string-composition. --- .../main/java/org/bouncycastle/asn1/x509/GeneralName.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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(); } From 2f06395214608e5929a93a0c61279feeeac23a73 Mon Sep 17 00:00:00 2001 From: mormao Date: Tue, 23 Jul 2024 16:40:40 +0200 Subject: [PATCH 30/45] avoid using StringBuffer, as they are synchronized, in favour of StringJoiner with prefix "[", suffix "]" and separator ", " --- .../asn1/x509/CertificatePolicies.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) 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; } } From a8bec74435c7d36e51061779adde3ad1132733c6 Mon Sep 17 00:00:00 2001 From: mormao Date: Tue, 23 Jul 2024 16:46:12 +0200 Subject: [PATCH 31/45] Replaced StringBuffer (which is synchronized) with StringBuilder --- .../org/bouncycastle/asn1/x509/CRLDistPoint.java | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) 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(); } From 8607f588a2125cebb579b607b7fa6f745c4e6f49 Mon Sep 17 00:00:00 2001 From: mormao Date: Tue, 23 Jul 2024 16:53:31 +0200 Subject: [PATCH 32/45] Replaced StringBuffer with StringBuilder and possibly joining elements of an iterable with a StringJoiner --- .../asn1/x509/PolicyInformation.java | 26 ++++++------------- 1 file changed, 8 insertions(+), 18 deletions(-) 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(); From d5df259703e5bc61c74d52f63a2f580b97463ad1 Mon Sep 17 00:00:00 2001 From: mormao Date: Tue, 23 Jul 2024 16:55:50 +0200 Subject: [PATCH 33/45] Replaced StringBuffer with a StringBuilder to avoid synchronization --- .../org/bouncycastle/asn1/x509/GeneralNames.java | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) 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(); } From a70ca0301f4b70267181862b4395c245ca2120d6 Mon Sep 17 00:00:00 2001 From: mormao Date: Tue, 23 Jul 2024 16:58:57 +0200 Subject: [PATCH 34/45] Replaced StringBuffer with a StringBuilder to avoid synchronization --- .../main/java/org/bouncycastle/asn1/x509/RoleSyntax.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) 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++) { From 0d784ef550847295cb6ccfd5133f53a2e39a56c2 Mon Sep 17 00:00:00 2001 From: mormao Date: Tue, 23 Jul 2024 17:09:55 +0200 Subject: [PATCH 35/45] Replaced StringBuffer with a StringBuilder to avoid synchronization --- .../org/bouncycastle/util/Fingerprint.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/org/bouncycastle/util/Fingerprint.java b/core/src/main/java/org/bouncycastle/util/Fingerprint.java index 7027d4948c..4c09530d5b 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,16 @@ 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]); + sb.append(':'); // eventually remove the last char after finishing (help branch prediction) } - return sb.toString(); + final int len = sb.length(); + return len == 0 ? "" : sb.deleteCharAt(len - 1).toString(); } public boolean equals(Object o) From fc53375c32e61c320a0456ff358b5be89200eb32 Mon Sep 17 00:00:00 2001 From: mormao Date: Tue, 23 Jul 2024 17:13:09 +0200 Subject: [PATCH 36/45] Replaced StringBuffer with a StringBuilder to avoid synchronization --- core/src/main/java/org/bouncycastle/util/Fingerprint.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/bouncycastle/util/Fingerprint.java b/core/src/main/java/org/bouncycastle/util/Fingerprint.java index 4c09530d5b..78314b4ea5 100644 --- a/core/src/main/java/org/bouncycastle/util/Fingerprint.java +++ b/core/src/main/java/org/bouncycastle/util/Fingerprint.java @@ -71,11 +71,13 @@ public String toString() { sb.append(encodingTable[(b >>> 4) & 0xf]); sb.append(encodingTable[b & 0x0f]); - sb.append(':'); // eventually remove the last char after finishing (help branch prediction) + // always add the separator, eventually substring + // to remove the last char after finishing (help branch prediction avoiding checks in the loop) + sb.append(':'); } final int len = sb.length(); - return len == 0 ? "" : sb.deleteCharAt(len - 1).toString(); + return len == 0 ? "" : sb.substring(0, len - 1); } public boolean equals(Object o) From 0963e3575be389622bf8fda7cdeb399eef57551e Mon Sep 17 00:00:00 2001 From: mormao Date: Tue, 23 Jul 2024 17:17:54 +0200 Subject: [PATCH 37/45] Replaced StringBuffer with a String composition (simpler, faster and null-safe) --- .../crypto/engines/CramerShoupCiphertext.java | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) 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; } /** From 7a06153702d2b4545504fa7f283860f88d342471 Mon Sep 17 00:00:00 2001 From: mormao Date: Tue, 23 Jul 2024 17:24:00 +0200 Subject: [PATCH 38/45] Replaced StringBuffer with a StringBuilder --- .../java/org/bouncycastle/i18n/LocalizedMessage.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) 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); From aabdb48ff5fdc788790811335b638e3dbe1e5dd1 Mon Sep 17 00:00:00 2001 From: mormao Date: Tue, 23 Jul 2024 17:34:23 +0200 Subject: [PATCH 39/45] Replaced StringBuffer with a StringBuilder to avoid synchronization --- .../main/java/org/bouncycastle/asn1/ASN1BitString.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) 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]); } From 93ee82167f60330e60af268971c7a058dec4ccb8 Mon Sep 17 00:00:00 2001 From: mormao Date: Tue, 23 Jul 2024 17:35:13 +0200 Subject: [PATCH 40/45] Replaced StringBuffer with a StringBuilder to avoid synchronization # Conflicts: # core/src/main/java/org/bouncycastle/asn1/ASN1RelativeOID.java --- core/src/main/java/org/bouncycastle/asn1/ASN1RelativeOID.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/bouncycastle/asn1/ASN1RelativeOID.java b/core/src/main/java/org/bouncycastle/asn1/ASN1RelativeOID.java index aff4b89b3b..aa75ace012 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(); + StringBuffer objId = new StringBuffer(); long value = 0; BigInteger bigValue = null; boolean first = true; From 264daab96828ba638b4665e30a74097584d8609a Mon Sep 17 00:00:00 2001 From: mormao Date: Wed, 24 Jul 2024 14:02:33 +0200 Subject: [PATCH 41/45] Replaced StringBuffer with a StringBuilder to avoid synchronization via a new context-aware Appendable --- .../org/bouncycastle/asn1/util/ASN1Dump.java | 546 +++++++++--------- .../org/bouncycastle/asn1/util/DERDump.java | 4 +- 2 files changed, 271 insertions(+), 279 deletions(-) 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..dedeec313d 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,20 @@ 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 String TAB = IndentingAppendable.TAB; private static final int SAMPLE_SIZE = 32; /** @@ -53,245 +23,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"); + 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"; } - else - { - buf.append("Set"); - } - buf.append(nl); - - ASN1Set set = (ASN1Set)obj; - String elementsIndent = indent + TAB; + buf.appendIndentedLine(description); - 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 + "] "); + 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 + "]"); } - else - { - buf.append(indent + "DER Octet String" + "[" + oct.getOctets().length + "] "); - } - if (verbose) - { - buf.append(dumpBinaryDataAsString(indent, oct.getOctets())); - } - else - { - buf.append(nl); - } - } - 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(); - - if (bitString instanceof DERBitString) - { - buf.append(indent + "DER Bit String" + "[" + bytes.length + ", " + padBits + "] "); + if (verbose) { + dumpBinaryDataAsString(buf, oct.getOctets()); + } else { + buf.append(NL); } - else if (bitString instanceof DLBitString) - { - buf.append(indent + "DL Bit String" + "[" + bytes.length + ", " + padBits + "] "); - } - else - { - buf.append(indent + "BER Bit String" + "[" + bytes.length + ", " + padBits + "] "); + } 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); } + buf.appendIndentedLine(line); - if (verbose) - { - buf.append(dumpBinaryDataAsString(indent, bytes)); - } - else - { - buf.append(nl); + if (verbose) { + dumpBinaryDataAsString(buf, bitString.getBytes()); + } else { + buf.appendLine(); } - } - 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 +205,7 @@ public static String dumpAsString( Object obj, boolean verbose) { - ASN1Primitive primitive; + final ASN1Primitive primitive; if (obj instanceof ASN1Primitive) { primitive = (ASN1Primitive)obj; @@ -329,58 +219,160 @@ 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); + } + + public IndentingAppendable(String indentWith) { + this(new StringBuilder(), indentWith); + } + + public IndentingAppendable(Appendable baseAppendable) { + this(baseAppendable, 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; + } + + public int getIndentLevel(){ + return indentLevel; + } + + 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(); } From 60fe02355ed516b0652d8c7db84ca790a0ccae57 Mon Sep 17 00:00:00 2001 From: mormao Date: Wed, 24 Jul 2024 14:21:41 +0200 Subject: [PATCH 42/45] Traverse the file system using java.io.File::getParent instead of substring by System's file separator, as it can lead to StringIndexOutOfBoundException in case the test folder does not exist --- .../org/bouncycastle/test/TestResourceFinder.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/core/src/test/java/org/bouncycastle/test/TestResourceFinder.java b/core/src/test/java/org/bouncycastle/test/TestResourceFinder.java index 14214bafae..b0892a9955 100644 --- a/core/src/test/java/org/bouncycastle/test/TestResourceFinder.java +++ b/core/src/test/java/org/bouncycastle/test/TestResourceFinder.java @@ -18,22 +18,23 @@ 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)); } } From 33e0e8029d30e887def5229fba8d1ada9e0cf79e Mon Sep 17 00:00:00 2001 From: mormao Date: Wed, 24 Jul 2024 14:25:05 +0200 Subject: [PATCH 43/45] Traverse the file system using java.io.File::getParent instead of substring by System's file separator, as it can lead to StringIndexOutOfBoundException in case the test folder does not exist --- .../src/test/java/org/bouncycastle/test/TestResourceFinder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/test/java/org/bouncycastle/test/TestResourceFinder.java b/core/src/test/java/org/bouncycastle/test/TestResourceFinder.java index b0892a9955..19e8a775b2 100644 --- a/core/src/test/java/org/bouncycastle/test/TestResourceFinder.java +++ b/core/src/test/java/org/bouncycastle/test/TestResourceFinder.java @@ -12,7 +12,7 @@ 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 From c1af7d20543cfd44b7900fbb5563b79c46848457 Mon Sep 17 00:00:00 2001 From: mormao Date: Wed, 24 Jul 2024 14:25:23 +0200 Subject: [PATCH 44/45] Deleted unused methods --- .../java/org/bouncycastle/asn1/util/ASN1Dump.java | 13 ------------- 1 file changed, 13 deletions(-) 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 dedeec313d..b40ff7c363 100644 --- a/core/src/main/java/org/bouncycastle/asn1/util/ASN1Dump.java +++ b/core/src/main/java/org/bouncycastle/asn1/util/ASN1Dump.java @@ -14,7 +14,6 @@ public class ASN1Dump { private static final String NL = System.lineSeparator(); - private static final String TAB = IndentingAppendable.TAB; private static final int SAMPLE_SIZE = 32; /** @@ -274,14 +273,6 @@ public IndentingAppendable() { this(new StringBuilder(), TAB); } - public IndentingAppendable(String indentWith) { - this(new StringBuilder(), indentWith); - } - - public IndentingAppendable(Appendable baseAppendable) { - this(baseAppendable, TAB); - } - private IndentingAppendable(Appendable baseAppendable, String indentWith) { this.baseAppendable = Objects.requireNonNull(baseAppendable, "base appendable"); this.indentWith = Objects.requireNonNull(indentWith, "indent string"); @@ -301,10 +292,6 @@ public IndentingAppendable decrementIndentLevel() { return this; } - public int getIndentLevel(){ - return indentLevel; - } - static String repeat(String base, int times) { Objects.requireNonNull(base, "repeated string"); if (times < 0) From 1b5d8bcba9b2d2c701ffe73c3fd5723a3cd9a9b2 Mon Sep 17 00:00:00 2001 From: mormao Date: Mon, 29 Jul 2024 09:10:10 +0200 Subject: [PATCH 45/45] test-created files removed from version control --- .gitignore | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) 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