diff --git a/itext.tests/itext.io.tests/itext/io/font/FontProgramTest.cs b/itext.tests/itext.io.tests/itext/io/font/FontProgramTest.cs
index 833d76bb66..a65a92e29a 100644
--- a/itext.tests/itext.io.tests/itext/io/font/FontProgramTest.cs
+++ b/itext.tests/itext.io.tests/itext/io/font/FontProgramTest.cs
@@ -32,6 +32,13 @@ namespace iText.IO.Font {
public class FontProgramTest : ExtendedITextTest {
private const String notExistingFont = "some-font.ttf";
+ [NUnit.Framework.SetUp]
+ public virtual void ClearFonts() {
+ FontProgramFactory.ClearRegisteredFonts();
+ FontProgramFactory.ClearRegisteredFontFamilies();
+ FontCache.ClearSavedFonts();
+ }
+
[NUnit.Framework.Test]
public virtual void ExceptionMessageTest() {
Exception e = NUnit.Framework.Assert.Catch(typeof(System.IO.IOException), () => FontProgramFactory.CreateFont
@@ -68,6 +75,16 @@ public virtual void RegisterDirectoryType1Test() {
.CurrentContext.TestDirectory) + "/resources/itext/io/font/type1/");
FontProgram computerModern = FontProgramFactory.CreateRegisteredFont("computer modern");
FontProgram cmr10 = FontProgramFactory.CreateRegisteredFont("cmr10");
+ NUnit.Framework.Assert.IsNull(computerModern);
+ NUnit.Framework.Assert.IsNull(cmr10);
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void RegisterDirectoryType1RecursivelyTest() {
+ FontProgramFactory.RegisterFontDirectoryRecursively(iText.Test.TestUtil.GetParentProjectDirectory(NUnit.Framework.TestContext
+ .CurrentContext.TestDirectory) + "/resources/itext/io/font/type1/");
+ FontProgram computerModern = FontProgramFactory.CreateRegisteredFont("computer modern");
+ FontProgram cmr10 = FontProgramFactory.CreateRegisteredFont("cmr10");
NUnit.Framework.Assert.IsNotNull(computerModern);
NUnit.Framework.Assert.IsNotNull(cmr10);
}
diff --git a/itext.tests/itext.io.tests/resources/itext/io/font/type1/cmr10.afm b/itext.tests/itext.io.tests/resources/itext/io/font/type1/testPackage/cmr10.afm
similarity index 100%
rename from itext.tests/itext.io.tests/resources/itext/io/font/type1/cmr10.afm
rename to itext.tests/itext.io.tests/resources/itext/io/font/type1/testPackage/cmr10.afm
diff --git a/itext.tests/itext.io.tests/resources/itext/io/font/type1/cmr10.pfb b/itext.tests/itext.io.tests/resources/itext/io/font/type1/testPackage/cmr10.pfb
similarity index 100%
rename from itext.tests/itext.io.tests/resources/itext/io/font/type1/cmr10.pfb
rename to itext.tests/itext.io.tests/resources/itext/io/font/type1/testPackage/cmr10.pfb
diff --git a/itext.tests/itext.io.tests/resources/itext/io/font/type1/cmr10.pfm b/itext.tests/itext.io.tests/resources/itext/io/font/type1/testPackage/cmr10.pfm
similarity index 100%
rename from itext.tests/itext.io.tests/resources/itext/io/font/type1/cmr10.pfm
rename to itext.tests/itext.io.tests/resources/itext/io/font/type1/testPackage/cmr10.pfm
diff --git a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfFontTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfFontTest.cs
index f059ed8119..42700399cd 100644
--- a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfFontTest.cs
+++ b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfFontTest.cs
@@ -1373,6 +1373,17 @@ public virtual void TestFontDirectoryRegister() {
pdfDoc.Close();
}
+ [NUnit.Framework.Test]
+ public virtual void FontDirectoryRegisterRecursivelyTest() {
+ PdfFontFactory.RegisterDirectoryRecursively(sourceFolder);
+ foreach (String name in PdfFontFactory.GetRegisteredFonts()) {
+ PdfFont pdfFont = PdfFontFactory.CreateRegisteredFont(name);
+ if (pdfFont == null) {
+ NUnit.Framework.Assert.IsTrue(false, "Font {" + name + "} can't be empty");
+ }
+ }
+ }
+
[NUnit.Framework.Test]
public virtual void FontRegisterTest() {
FontProgramFactory.RegisterFont(fontsFolder + "NotoSerif-Regular_v1.7.ttf", "notoSerifRegular");
diff --git a/itext.tests/itext.kernel.tests/itext/kernel/pdf/tagging/PdfStructElemUnitTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/pdf/tagging/PdfStructElemUnitTest.cs
index db8da2c1dc..653bd3d45c 100644
--- a/itext.tests/itext.kernel.tests/itext/kernel/pdf/tagging/PdfStructElemUnitTest.cs
+++ b/itext.tests/itext.kernel.tests/itext/kernel/pdf/tagging/PdfStructElemUnitTest.cs
@@ -21,6 +21,7 @@ You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
using System;
+using System.Collections.Generic;
using iText.IO.Source;
using iText.Kernel.Exceptions;
using iText.Kernel.Geom;
@@ -51,5 +52,46 @@ public virtual void AnnotationHasNoReferenceToPageTest() {
NUnit.Framework.Assert.AreEqual(KernelExceptionMessageConstant.ANNOTATION_SHALL_HAVE_REFERENCE_TO_PAGE, exception
.Message);
}
+
+ [NUnit.Framework.Test]
+ public virtual void AttributesAreNullTest() {
+ IDictionary attributesMap = new Dictionary();
+ PdfDictionary dictionary = new PdfDictionary(attributesMap);
+ PdfStructElem pdfStructElem = new PdfStructElem(dictionary);
+ IList actualAttributesList = pdfStructElem.GetAttributesList();
+ IList expectedAttributesList = new List();
+ NUnit.Framework.Assert.AreEqual(actualAttributesList, expectedAttributesList);
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void AttributesAreDictionaryTest() {
+ IDictionary attributesMap = new Dictionary();
+ IDictionary dictionaryMap = new Dictionary();
+ dictionaryMap.Put(PdfName.A, new PdfName("value"));
+ attributesMap.Put(PdfName.A, new PdfDictionary(dictionaryMap));
+ PdfDictionary dictionary = new PdfDictionary(attributesMap);
+ PdfStructElem pdfStructElem = new PdfStructElem(dictionary);
+ IList actualAttributesList = pdfStructElem.GetAttributesList();
+ IList expectedAttributesList = new List();
+ expectedAttributesList.Add(new PdfStructureAttributes(new PdfDictionary(dictionaryMap)));
+ NUnit.Framework.Assert.AreEqual(actualAttributesList[0].GetPdfObject().Get(PdfName.A), expectedAttributesList
+ [0].GetPdfObject().Get(PdfName.A));
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void AttributesAreArrayTest() {
+ IDictionary attributesMap = new Dictionary();
+ IDictionary dictionaryMap = new Dictionary();
+ dictionaryMap.Put(PdfName.A, new PdfName("value"));
+ PdfDictionary pdfDictionary = new PdfDictionary(dictionaryMap);
+ attributesMap.Put(PdfName.A, new PdfArray(pdfDictionary));
+ PdfDictionary dictionary = new PdfDictionary(attributesMap);
+ PdfStructElem pdfStructElem = new PdfStructElem(dictionary);
+ IList actualAttributesList = pdfStructElem.GetAttributesList();
+ IList expectedAttributesList = new List();
+ expectedAttributesList.Add(new PdfStructureAttributes(new PdfDictionary(dictionaryMap)));
+ NUnit.Framework.Assert.AreEqual(actualAttributesList[0].GetPdfObject().Get(PdfName.A), expectedAttributesList
+ [0].GetPdfObject().Get(PdfName.A));
+ }
}
}
diff --git a/itext.tests/itext.kernel.tests/itext/kernel/pdf/tagging/PdfStructureAttributesTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/pdf/tagging/PdfStructureAttributesTest.cs
new file mode 100644
index 0000000000..b177dca901
--- /dev/null
+++ b/itext.tests/itext.kernel.tests/itext/kernel/pdf/tagging/PdfStructureAttributesTest.cs
@@ -0,0 +1,46 @@
+/*
+This file is part of the iText (R) project.
+Copyright (c) 1998-2025 Apryse Group NV
+Authors: Apryse Software.
+
+This program is offered under a commercial and under the AGPL license.
+For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below.
+
+AGPL licensing:
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program. If not, see .
+*/
+using System;
+using System.Collections.Generic;
+using iText.Kernel.Pdf;
+using iText.Test;
+
+namespace iText.Kernel.Pdf.Tagging {
+ [NUnit.Framework.Category("UnitTest")]
+ public class PdfStructureAttributesTest : ExtendedITextTest {
+ [NUnit.Framework.Test]
+ public virtual void OwnerIsNullTest() {
+ PdfStructureAttributes pdfStructureAttributes = new PdfStructureAttributes(new PdfDictionary());
+ NUnit.Framework.Assert.IsNull(pdfStructureAttributes.GetPdfOwner());
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void OwnerIsNotNullTest() {
+ IDictionary map = new Dictionary();
+ map.Put(PdfName.O, new PdfName("owner"));
+ PdfStructureAttributes pdfStructureAttributes = new PdfStructureAttributes(new PdfDictionary(map));
+ String pdfOwner = pdfStructureAttributes.GetPdfOwner();
+ NUnit.Framework.Assert.AreEqual("owner", pdfOwner);
+ }
+ }
+}
diff --git a/itext.tests/itext.sign.tests/itext/signatures/validation/AssertValidationReport.cs b/itext.tests/itext.sign.tests/itext/signatures/validation/AssertValidationReport.cs
index 545f92b487..b5ac802a65 100644
--- a/itext.tests/itext.sign.tests/itext/signatures/validation/AssertValidationReport.cs
+++ b/itext.tests/itext.sign.tests/itext/signatures/validation/AssertValidationReport.cs
@@ -127,6 +127,12 @@ public AssertValidationReport.AssertValidationReportLogItem WithMessage(String m
return this;
}
+ public virtual AssertValidationReport.AssertValidationReportLogItem WithMessageContains(String expectedContent
+ ) {
+ check.WithMessageContains(expectedContent);
+ return this;
+ }
+
public virtual AssertValidationReport.AssertValidationReportLogItem WithStatus(ReportItem.ReportItemStatus
status) {
check.WithStatus(status);
@@ -219,6 +225,8 @@ private class ValidationReportLogItemCheck : AssertValidationReport.CheckChain {
private String message;
+ private String expectedMessageContent;
+
private ReportItem.ReportItemStatus status;
private bool checkStatus = false;
@@ -245,6 +253,11 @@ public virtual void WithMessage(String message, params Func[
errorMessage.Append(" message '").Append(message).Append("'");
}
+ public virtual void WithMessageContains(String expectedContent) {
+ this.expectedMessageContent = expectedContent;
+ errorMessage.Append(" message containing '").Append(expectedContent).Append("'");
+ }
+
public virtual void WithStatus(ReportItem.ReportItemStatus status) {
this.status = status;
checkStatus = true;
@@ -276,7 +289,13 @@ protected internal override void Check(ValidationReport report, AssertValidation
errorMessage.Append("found ").Append(prefiltered.Count).Append(" matches after message filter\n");
}
else {
- prefiltered = report.GetLogs();
+ if (expectedMessageContent != null) {
+ prefiltered = report.GetLogs().Where((i) => i.GetMessage().Contains(expectedMessageContent)).ToList();
+ errorMessage.Append("found ").Append(prefiltered.Count).Append(" matches after message filter\n");
+ }
+ else {
+ prefiltered = report.GetLogs();
+ }
}
if (checkName != null) {
prefiltered = prefiltered.Where((i) => (checkName.Equals(i.GetCheckName()))).ToList();
diff --git a/itext.tests/itext.sign.tests/itext/signatures/validation/CertificateChainValidatorTest.cs b/itext.tests/itext.sign.tests/itext/signatures/validation/CertificateChainValidatorTest.cs
index 01499c989e..bdd2af3134 100644
--- a/itext.tests/itext.sign.tests/itext/signatures/validation/CertificateChainValidatorTest.cs
+++ b/itext.tests/itext.sign.tests/itext/signatures/validation/CertificateChainValidatorTest.cs
@@ -22,10 +22,10 @@ You should have received a copy of the GNU Affero General Public License
*/
using System;
using System.IO;
+using System.Text;
using iText.Commons.Bouncycastle.Cert;
using iText.Commons.Bouncycastle.Security;
using iText.Commons.Utils;
-using iText.Kernel.Crypto;
using iText.Signatures;
using iText.Signatures.Testutils;
using iText.Signatures.Validation.Context;
@@ -116,9 +116,11 @@ public virtual void InvalidNumericBasicConstraintsTest() {
(2).HasNumberOfLogs(3).HasLogItem((la) => la.WithCheckName(CertificateChainValidator.CERTIFICATE_CHECK
).WithMessage("Certificate {0} is trusted, revocation data checks are not required.", (l) => rootCert.
GetSubjectDN()).WithCertificate(rootCert)).HasLogItem((la) => la.WithCheckName(CertificateChainValidator
- .EXTENSIONS_CHECK).WithMessage(CertificateChainValidator.EXTENSION_MISSING, (l) => "2.5.29.19").WithCertificate
- (rootCert)).HasLogItem((la) => la.WithCheckName(CertificateChainValidator.EXTENSIONS_CHECK).WithMessage
- (CertificateChainValidator.EXTENSION_MISSING, (l) => "2.5.29.19").WithCertificate(intermediateCert)));
+ .EXTENSIONS_CHECK).WithMessage(CertificateChainValidator.EXTENSION_MISSING, (l) => MessageFormatUtil.Format
+ (DynamicBasicConstraintsExtension.ERROR_MESSAGE, 1, 0)).WithCertificate(rootCert)).HasLogItem((la) =>
+ la.WithCheckName(CertificateChainValidator.EXTENSIONS_CHECK).WithMessage(CertificateChainValidator.EXTENSION_MISSING
+ , (l) => MessageFormatUtil.Format(DynamicBasicConstraintsExtension.ERROR_MESSAGE, 0, -1)).WithCertificate
+ (intermediateCert)));
}
[NUnit.Framework.Test]
@@ -127,7 +129,7 @@ public virtual void ChainWithAiaTest() {
IX509Certificate[] certificateChain = PemFileHelper.ReadFirstChain(chainName);
IX509Certificate signingCert = (IX509Certificate)certificateChain[0];
IX509Certificate rootCert = (IX509Certificate)certificateChain[2];
- IssuingCertificateRetriever customRetriever = new _IssuingCertificateRetriever_182();
+ IssuingCertificateRetriever customRetriever = new _IssuingCertificateRetriever_183();
validatorChainBuilder.WithIssuingCertificateRetrieverFactory(() => customRetriever);
CertificateChainValidator validator = validatorChainBuilder.BuildCertificateChainValidator();
properties.SetRequiredExtensions(CertificateSources.Of(CertificateSource.CERT_ISSUER), JavaCollectionsUtil
@@ -138,8 +140,8 @@ public virtual void ChainWithAiaTest() {
AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID));
}
- private sealed class _IssuingCertificateRetriever_182 : IssuingCertificateRetriever {
- public _IssuingCertificateRetriever_182() {
+ private sealed class _IssuingCertificateRetriever_183 : IssuingCertificateRetriever {
+ public _IssuingCertificateRetriever_183() {
}
protected internal override Stream GetIssuerCertByURI(String uri) {
@@ -155,7 +157,7 @@ public virtual void ChainWithAiaWhichPointsToRandomCertTest() {
IX509Certificate signingCert = (IX509Certificate)certificateChain[0];
IX509Certificate intermediateCert = (IX509Certificate)certificateChain[1];
IX509Certificate rootCert = (IX509Certificate)certificateChain[2];
- IssuingCertificateRetriever customRetriever = new _IssuingCertificateRetriever_206();
+ IssuingCertificateRetriever customRetriever = new _IssuingCertificateRetriever_207();
validatorChainBuilder.WithIssuingCertificateRetrieverFactory(() => customRetriever);
CertificateChainValidator validator = validatorChainBuilder.BuildCertificateChainValidator();
properties.SetRequiredExtensions(CertificateSources.Of(CertificateSource.CERT_ISSUER), JavaCollectionsUtil
@@ -168,8 +170,8 @@ public virtual void ChainWithAiaWhichPointsToRandomCertTest() {
AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID));
}
- private sealed class _IssuingCertificateRetriever_206 : IssuingCertificateRetriever {
- public _IssuingCertificateRetriever_206() {
+ private sealed class _IssuingCertificateRetriever_207 : IssuingCertificateRetriever {
+ public _IssuingCertificateRetriever_207() {
}
protected internal override Stream GetIssuerCertByURI(String uri) {
@@ -228,13 +230,13 @@ public virtual void SeveralFailuresWithProceedAfterFailTest() {
CertificateReportItem failure1 = report.GetCertificateFailures()[0];
NUnit.Framework.Assert.AreEqual(intermediateCert, failure1.GetCertificate());
NUnit.Framework.Assert.AreEqual("Required certificate extensions check.", failure1.GetCheckName());
- NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format("Required extension {0} is missing or incorrect."
- , OID.X509Extensions.KEY_USAGE), failure1.GetMessage());
+ NUnit.Framework.Assert.AreEqual(BuildKeyUsageWrongMessagePart(KeyUsage.DECIPHER_ONLY, KeyUsage.KEY_CERT_SIGN
+ ), failure1.GetMessage());
CertificateReportItem failure2 = report.GetCertificateFailures()[1];
NUnit.Framework.Assert.AreEqual(rootCert, failure2.GetCertificate());
NUnit.Framework.Assert.AreEqual("Required certificate extensions check.", failure2.GetCheckName());
- NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format("Required extension {0} is missing or incorrect."
- , OID.X509Extensions.KEY_USAGE), failure2.GetMessage());
+ NUnit.Framework.Assert.AreEqual(BuildKeyUsageWrongMessagePart(KeyUsage.DECIPHER_ONLY, KeyUsage.KEY_CERT_SIGN
+ ), failure2.GetMessage());
}
[NUnit.Framework.Test]
@@ -260,8 +262,8 @@ public virtual void SeveralFailuresWithoutProceedAfterFailTest() {
CertificateReportItem failure1 = report.GetCertificateFailures()[0];
NUnit.Framework.Assert.AreEqual(intermediateCert, failure1.GetCertificate());
NUnit.Framework.Assert.AreEqual("Required certificate extensions check.", failure1.GetCheckName());
- NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format("Required extension {0} is missing or incorrect."
- , OID.X509Extensions.KEY_USAGE), failure1.GetMessage());
+ NUnit.Framework.Assert.AreEqual(BuildKeyUsageWrongMessagePart(KeyUsage.DECIPHER_ONLY, KeyUsage.KEY_CERT_SIGN
+ ), failure1.GetMessage());
}
[NUnit.Framework.Test]
@@ -331,8 +333,8 @@ public virtual void ValidChainRequiredExtensionNegativeTest() {
AssertValidationReport.AssertThat(report, (a) => a.HasNumberOfFailures(1).HasNumberOfLogs(2).HasLogItem((la
) => la.WithCheckName(CertificateChainValidator.CERTIFICATE_CHECK).WithMessage(CertificateChainValidator
.CERTIFICATE_TRUSTED, (l) => rootCert.GetSubjectDN()).WithCertificate(rootCert)).HasLogItem((la) => la
- .WithCheckName(CertificateChainValidator.EXTENSIONS_CHECK).WithMessage(CertificateChainValidator.EXTENSION_MISSING
- , (l) => OID.X509Extensions.KEY_USAGE).WithCertificate(signingCert)));
+ .WithCheckName(CertificateChainValidator.EXTENSIONS_CHECK).WithMessageContains(BuildKeyUsageWrongMessagePart
+ (KeyUsage.KEY_CERT_SIGN)).WithCertificate(signingCert)));
}
[NUnit.Framework.Test]
@@ -672,5 +674,17 @@ public virtual void TestStopOnInvalidRevocationResultTest() {
NUnit.Framework.Assert.AreEqual(0, mockCertificateRetriever.getCrlIssuerCertificatesByNameCalls.Count);
NUnit.Framework.Assert.AreEqual(1, mockRevocationDataValidator.calls.Count);
}
+
+ private String BuildKeyUsageWrongMessagePart(KeyUsage expectedKeyUsage, params KeyUsage[] actualKeyUsage) {
+ StringBuilder stringBuilder = new StringBuilder();
+ String sep = "";
+ foreach (KeyUsage usage in actualKeyUsage) {
+ stringBuilder.Append(sep).Append(usage);
+ sep = ", ";
+ }
+ return MessageFormatUtil.Format(CertificateChainValidator.EXTENSION_MISSING, MessageFormatUtil.Format(KeyUsageExtension
+ .EXPECTED_VALUE, expectedKeyUsage) + MessageFormatUtil.Format(KeyUsageExtension.ACTUAL_VALUE, stringBuilder
+ .ToString()));
+ }
}
}
diff --git a/itext.tests/itext.sign.tests/itext/signatures/validation/OCSPValidatorIntegrationTest.cs b/itext.tests/itext.sign.tests/itext/signatures/validation/OCSPValidatorIntegrationTest.cs
index 1d4e4ad238..8519b8d68e 100644
--- a/itext.tests/itext.sign.tests/itext/signatures/validation/OCSPValidatorIntegrationTest.cs
+++ b/itext.tests/itext.sign.tests/itext/signatures/validation/OCSPValidatorIntegrationTest.cs
@@ -27,12 +27,12 @@ You should have received a copy of the GNU Affero General Public License
using iText.Commons.Bouncycastle.Cert;
using iText.Commons.Bouncycastle.Crypto;
using iText.Commons.Utils;
-using iText.Kernel.Crypto;
using iText.Signatures;
using iText.Signatures.Testutils;
using iText.Signatures.Testutils.Builder;
using iText.Signatures.Testutils.Client;
using iText.Signatures.Validation.Context;
+using iText.Signatures.Validation.Extensions;
using iText.Signatures.Validation.Report;
using iText.Test;
@@ -157,9 +157,8 @@ public virtual void AuthorizedOcspResponderDoesNotHaveOcspSigningExtensionTest()
validator.Validate(report, baseContext, checkCert, basicOCSPResp.GetResponses()[0], basicOCSPResp, TimeTestUtil
.TEST_DATE_TIME, TimeTestUtil.TEST_DATE_TIME);
AssertValidationReport.AssertThat(report, (a) => a.HasNumberOfFailures(1).HasLogItem((al) => al.WithCheckName
- (CertificateChainValidator.EXTENSIONS_CHECK).WithMessage(CertificateChainValidator.EXTENSION_MISSING,
- (l) => OID.X509Extensions.EXTENDED_KEY_USAGE)).HasStatus(ValidationReport.ValidationResult.INDETERMINATE
- ));
+ (CertificateChainValidator.EXTENSIONS_CHECK).WithMessageContains(ExtendedKeyUsageExtension.OCSP_SIGNING
+ )).HasStatus(ValidationReport.ValidationResult.INDETERMINATE));
}
[NUnit.Framework.Test]
diff --git a/itext.tests/itext.sign.tests/itext/signatures/validation/extensions/KeyUsageExtensionTest.cs b/itext.tests/itext.sign.tests/itext/signatures/validation/extensions/KeyUsageExtensionTest.cs
index 0f1d1ba3ff..910cd02457 100644
--- a/itext.tests/itext.sign.tests/itext/signatures/validation/extensions/KeyUsageExtensionTest.cs
+++ b/itext.tests/itext.sign.tests/itext/signatures/validation/extensions/KeyUsageExtensionTest.cs
@@ -23,6 +23,7 @@ You should have received a copy of the GNU Affero General Public License
using System;
using iText.Commons.Bouncycastle.Cert;
using iText.Commons.Utils;
+using iText.Signatures;
using iText.Signatures.Testutils;
using iText.Test;
@@ -158,5 +159,38 @@ public virtual void KeyUsageSeveralKeys2PartiallyNotExpectedTest() {
, KeyUsage.DIGITAL_SIGNATURE));
NUnit.Framework.Assert.IsFalse(extension.ExistsInCertificate(certificate));
}
+
+ [NUnit.Framework.Test]
+ public virtual void KeyUsageTranslationTest() {
+ String certName = certsSrc + "keyUsageDecipherOnlyCert.pem";
+ KeyUsageExtension extension = new KeyUsageExtension(KeyUsage.DECIPHER_ONLY);
+ IX509Certificate certificate = (IX509Certificate)PemFileHelper.ReadFirstChain(certName)[0];
+ NUnit.Framework.Assert.AreEqual(CertificateUtil.GetExtensionValue(certificate, extension.GetExtensionOid()
+ ), extension.GetExtensionValue());
+ certName = certsSrc + "keyUsageDigitalSignatureCert.pem";
+ extension = new KeyUsageExtension(KeyUsage.DIGITAL_SIGNATURE);
+ certificate = (IX509Certificate)PemFileHelper.ReadFirstChain(certName)[0];
+ NUnit.Framework.Assert.AreEqual(CertificateUtil.GetExtensionValue(certificate, extension.GetExtensionOid()
+ ), extension.GetExtensionValue());
+ certName = certsSrc + "keyUsageKeyCertSignCert.pem";
+ extension = new KeyUsageExtension(KeyUsage.KEY_CERT_SIGN);
+ certificate = (IX509Certificate)PemFileHelper.ReadFirstChain(certName)[0];
+ NUnit.Framework.Assert.AreEqual(CertificateUtil.GetExtensionValue(certificate, extension.GetExtensionOid()
+ ), extension.GetExtensionValue());
+ certName = certsSrc + "keyUsageSeveralKeys1Cert.pem";
+ //Non-Repudiation, Key Encipherment, Off-line CRL Signing, CRL Signing
+ extension = new KeyUsageExtension(JavaUtil.ArraysAsList(KeyUsage.NON_REPUDIATION, KeyUsage.KEY_ENCIPHERMENT
+ , KeyUsage.CRL_SIGN));
+ certificate = (IX509Certificate)PemFileHelper.ReadFirstChain(certName)[0];
+ NUnit.Framework.Assert.AreEqual(CertificateUtil.GetExtensionValue(certificate, extension.GetExtensionOid()
+ ), extension.GetExtensionValue());
+ certName = certsSrc + "keyUsageSeveralKeys2Cert.pem";
+ //Digital Signature, Key Agreement, Decipher Only
+ extension = new KeyUsageExtension(JavaUtil.ArraysAsList(KeyUsage.DIGITAL_SIGNATURE, KeyUsage.KEY_AGREEMENT
+ , KeyUsage.DECIPHER_ONLY));
+ certificate = (IX509Certificate)PemFileHelper.ReadFirstChain(certName)[0];
+ NUnit.Framework.Assert.AreEqual(CertificateUtil.GetExtensionValue(certificate, extension.GetExtensionOid()
+ ), extension.GetExtensionValue());
+ }
}
}
diff --git a/itext/itext.io/itext/io/font/FontProgramFactory.cs b/itext/itext.io/itext/io/font/FontProgramFactory.cs
index b75caaa39e..af6ebafd42 100644
--- a/itext/itext.io/itext/io/font/FontProgramFactory.cs
+++ b/itext/itext.io/itext/io/font/FontProgramFactory.cs
@@ -495,6 +495,13 @@ public static int RegisterFontDirectory(String dir) {
return fontRegisterProvider.RegisterFontDirectory(dir);
}
+ /// Register all the fonts in a directory recursively.
+ /// the directory
+ /// the number of fonts registered
+ public static int RegisterFontDirectoryRecursively(String dir) {
+ return fontRegisterProvider.RegisterFontDirectory(dir, true);
+ }
+
/// Register fonts in some probable directories.
///
/// Register fonts in some probable directories. It usually works in Windows,
diff --git a/itext/itext.kernel/itext/kernel/font/PdfFontFactory.cs b/itext/itext.kernel/itext/kernel/font/PdfFontFactory.cs
index a059ad5fd7..d67e6cf7cb 100644
--- a/itext/itext.kernel/itext/kernel/font/PdfFontFactory.cs
+++ b/itext/itext.kernel/itext/kernel/font/PdfFontFactory.cs
@@ -659,6 +659,7 @@ public static PdfType3Font CreateType3Font(PdfDocument document, String fontName
///
///
///
+ ///
///
///
///
@@ -705,6 +706,7 @@ public static PdfFont CreateRegisteredFont(String fontName, String encoding, Pdf
///
///
///
+ ///
///
///
///
@@ -749,6 +751,7 @@ public static PdfFont CreateRegisteredFont(String fontName, String encoding, Pdf
///
///
///
+ ///
///
///
///
@@ -797,6 +800,7 @@ public static PdfFont CreateRegisteredFont(String fontName, String encoding, Pdf
///
///
///
+ ///
///
///
///
@@ -835,6 +839,7 @@ public static PdfFont CreateRegisteredFont(String fontName, String encoding, Pdf
///
///
///
+ ///
///
///
///
@@ -868,6 +873,7 @@ public static PdfFont CreateRegisteredFont(String fontName, String encoding) {
///
///
///
+ ///
///
///
///
@@ -908,6 +914,13 @@ public static int RegisterDirectory(String dirPath) {
return FontProgramFactory.RegisterFontDirectory(dirPath);
}
+ /// Registers all the fonts in a directory recursively.
+ /// the directory path to be registered as a font directory path
+ /// the number of fonts registered
+ public static int RegisterDirectoryRecursively(String dirPath) {
+ return FontProgramFactory.RegisterFontDirectoryRecursively(dirPath);
+ }
+
/// Register fonts in some probable directories.
///
/// Register fonts in some probable directories. It usually works in Windows,
diff --git a/itext/itext.kernel/itext/kernel/pdf/tagging/PdfStructElem.cs b/itext/itext.kernel/itext/kernel/pdf/tagging/PdfStructElem.cs
index 25bdfd1fdc..da6598bd8b 100644
--- a/itext/itext.kernel/itext/kernel/pdf/tagging/PdfStructElem.cs
+++ b/itext/itext.kernel/itext/kernel/pdf/tagging/PdfStructElem.cs
@@ -109,6 +109,29 @@ public virtual PdfObject GetAttributes(bool createNewIfNull) {
return attributes;
}
+ /// Gets a list of PDF attribute objects.
+ /// list of PDF attribute objects.
+ public virtual IList GetAttributesList() {
+ IList attributesList = new List();
+ PdfObject elemAttributesObj = GetAttributes(false);
+ if (elemAttributesObj != null) {
+ if (elemAttributesObj.IsDictionary()) {
+ attributesList.Add(new PdfStructureAttributes((PdfDictionary)elemAttributesObj));
+ }
+ else {
+ if (elemAttributesObj.IsArray()) {
+ PdfArray attributesArray = (PdfArray)elemAttributesObj;
+ foreach (PdfObject attributeObj in attributesArray) {
+ if (attributeObj.IsDictionary()) {
+ attributesList.Add(new PdfStructureAttributes((PdfDictionary)attributeObj));
+ }
+ }
+ }
+ }
+ }
+ return attributesList;
+ }
+
public virtual void SetAttributes(PdfObject attributes) {
Put(PdfName.A, attributes);
}
diff --git a/itext/itext.kernel/itext/kernel/pdf/tagging/PdfStructureAttributes.cs b/itext/itext.kernel/itext/kernel/pdf/tagging/PdfStructureAttributes.cs
index ce53283956..73c50e21c1 100644
--- a/itext/itext.kernel/itext/kernel/pdf/tagging/PdfStructureAttributes.cs
+++ b/itext/itext.kernel/itext/kernel/pdf/tagging/PdfStructureAttributes.cs
@@ -35,6 +35,13 @@ public PdfStructureAttributes(String owner)
GetPdfObject().Put(PdfName.O, PdfStructTreeRoot.ConvertRoleToPdfName(owner));
}
+ /// Method to get owner of current pdf object.
+ /// Pdf owner
+ public virtual String GetPdfOwner() {
+ PdfName pdfName = (PdfName)GetPdfObject().Get(PdfName.O);
+ return pdfName == null ? null : pdfName.GetValue();
+ }
+
public PdfStructureAttributes(PdfNamespace @namespace)
: base(new PdfDictionary()) {
GetPdfObject().Put(PdfName.O, PdfName.NSO);
diff --git a/itext/itext.sign/itext/signatures/validation/CertificateChainValidator.cs b/itext/itext.sign/itext/signatures/validation/CertificateChainValidator.cs
index ce52c1323d..963085ae86 100644
--- a/itext/itext.sign/itext/signatures/validation/CertificateChainValidator.cs
+++ b/itext/itext.sign/itext/signatures/validation/CertificateChainValidator.cs
@@ -55,7 +55,7 @@ public class CertificateChainValidator {
//\endcond
//\cond DO_NOT_DOCUMENT
- internal const String EXTENSION_MISSING = "Required extension {0} is missing or incorrect.";
+ internal const String EXTENSION_MISSING = "Required extension validation failed: {0}";
//\endcond
//\cond DO_NOT_DOCUMENT
@@ -290,7 +290,7 @@ private void ValidateRequiredExtensions(ValidationReport result, ValidationConte
}
if (!requiredExtension.ExistsInCertificate(certificate)) {
result.AddReportItem(new CertificateReportItem(certificate, EXTENSIONS_CHECK, MessageFormatUtil.Format(EXTENSION_MISSING
- , requiredExtension.GetExtensionOid()), ReportItem.ReportItemStatus.INVALID));
+ , requiredExtension.GetMessage()), ReportItem.ReportItemStatus.INVALID));
}
}
}
diff --git a/itext/itext.sign/itext/signatures/validation/extensions/CertificateExtension.cs b/itext/itext.sign/itext/signatures/validation/extensions/CertificateExtension.cs
index 39fa7e8e0e..d66f1ba758 100644
--- a/itext/itext.sign/itext/signatures/validation/extensions/CertificateExtension.cs
+++ b/itext/itext.sign/itext/signatures/validation/extensions/CertificateExtension.cs
@@ -29,10 +29,20 @@ You should have received a copy of the GNU Affero General Public License
namespace iText.Signatures.Validation.Extensions {
/// Class representing certificate extension with all the information required for validation.
public class CertificateExtension {
+ public const String EXCEPTION_OCCURRED = " but an exception occurred {0}:{1}.";
+
+ public const String EXTENSION_NOT_FOUND = " but no extension with that id was found.";
+
+ public const String FOUND_VALUE = " but found value ";
+
+ public const String EXPECTED_EXTENSION_ID_AND_VALUE = "Expected extension with id {0} and value {1}" + " {1} {2}";
+
private readonly String extensionOid;
private readonly IAsn1Object extensionValue;
+ private String errorMessage = "";
+
///
/// Create new instance of
///
@@ -73,6 +83,13 @@ public virtual String GetExtensionOid() {
return extensionOid;
}
+ /// Returns a message with extra information about the check.
+ /// a message with extra information about the check.
+ public virtual String GetMessage() {
+ return MessageFormatUtil.Format(EXPECTED_EXTENSION_ID_AND_VALUE, GetExtensionOid(), GetExtensionValue().ToString
+ (), errorMessage);
+ }
+
/// Check if this extension is present in the provided certificate.
///
/// Check if this extension is present in the provided certificate.
@@ -97,13 +114,26 @@ public virtual bool ExistsInCertificate(IX509Certificate certificate) {
try {
providedExtensionValue = CertificateUtil.GetExtensionValue(certificate, extensionOid);
}
- catch (System.IO.IOException) {
+ catch (System.IO.IOException e) {
+ errorMessage = MessageFormatUtil.Format(EXCEPTION_OCCURRED, e.GetType().FullName, e.Message);
+ return false;
+ }
+ catch (Exception e) {
+ errorMessage = MessageFormatUtil.Format(EXCEPTION_OCCURRED, e.GetType().FullName, e.Message);
return false;
}
- catch (Exception) {
+ if (providedExtensionValue == null) {
+ if (extensionValue == null) {
+ return true;
+ }
+ errorMessage = EXTENSION_NOT_FOUND;
return false;
}
- return Object.Equals(providedExtensionValue, extensionValue);
+ if (Object.Equals(providedExtensionValue, extensionValue)) {
+ return true;
+ }
+ errorMessage = FOUND_VALUE + MessageFormatUtil.Format(" but found value {0}.", extensionValue.ToString());
+ return false;
}
public override bool Equals(Object o) {
diff --git a/itext/itext.sign/itext/signatures/validation/extensions/DynamicBasicConstraintsExtension.cs b/itext/itext.sign/itext/signatures/validation/extensions/DynamicBasicConstraintsExtension.cs
index d6b2957465..342fa86060 100644
--- a/itext/itext.sign/itext/signatures/validation/extensions/DynamicBasicConstraintsExtension.cs
+++ b/itext/itext.sign/itext/signatures/validation/extensions/DynamicBasicConstraintsExtension.cs
@@ -20,9 +20,11 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
+using System;
using iText.Bouncycastleconnector;
using iText.Commons.Bouncycastle;
using iText.Commons.Bouncycastle.Cert;
+using iText.Commons.Utils;
using iText.Kernel.Crypto;
namespace iText.Signatures.Validation.Extensions {
@@ -33,6 +35,10 @@ namespace iText.Signatures.Validation.Extensions {
public class DynamicBasicConstraintsExtension : DynamicCertificateExtension {
private static readonly IBouncyCastleFactory FACTORY = BouncyCastleFactoryCreator.GetFactory();
+ public const String ERROR_MESSAGE = "Expected extension 2.5.29.19 to have a value of at least {0} but found {1}";
+
+ private String errorMessage;
+
///
/// Create new instance of
/// .
@@ -62,7 +68,16 @@ public DynamicBasicConstraintsExtension()
/// otherwise
///
public override bool ExistsInCertificate(IX509Certificate certificate) {
- return certificate.GetBasicConstraints() >= GetCertificateChainSize() - 1;
+ if (certificate.GetBasicConstraints() >= GetCertificateChainSize() - 1) {
+ return true;
+ }
+ errorMessage = MessageFormatUtil.Format(ERROR_MESSAGE, GetCertificateChainSize() - 1, certificate.GetBasicConstraints
+ ());
+ return false;
+ }
+
+ public override String GetMessage() {
+ return errorMessage;
}
}
}
diff --git a/itext/itext.sign/itext/signatures/validation/extensions/ExtendedKeyUsageExtension.cs b/itext/itext.sign/itext/signatures/validation/extensions/ExtendedKeyUsageExtension.cs
index cd377408bf..d243e77be0 100644
--- a/itext/itext.sign/itext/signatures/validation/extensions/ExtendedKeyUsageExtension.cs
+++ b/itext/itext.sign/itext/signatures/validation/extensions/ExtendedKeyUsageExtension.cs
@@ -22,12 +22,14 @@ You should have received a copy of the GNU Affero General Public License
*/
using System;
using System.Collections.Generic;
+using System.Text;
using iText.Bouncycastleconnector;
using iText.Commons.Bouncycastle;
using iText.Commons.Bouncycastle.Asn1;
using iText.Commons.Bouncycastle.Cert;
using iText.Commons.Bouncycastle.Security;
using iText.Kernel.Crypto;
+using Microsoft.Extensions.Primitives;
namespace iText.Signatures.Validation.Extensions {
/// Class representing "Extended Key Usage" extension.
@@ -44,8 +46,16 @@ public class ExtendedKeyUsageExtension : CertificateExtension {
private static readonly IBouncyCastleFactory FACTORY = BouncyCastleFactoryCreator.GetFactory();
+ public const String EXPECTED_KEY_USAGES = "Expected extended key usages:";
+ public const String ACTUAL = "But found :";
+ public const String NO_EXTENDED_KEY_USAGES_WERE_FOUND = " But no extended key usages were found.";
+ public const String ERROR_OCCURRED_DURING_RETRIEVAL = " But error occurred during retrieval ";
+
+
private readonly IList extendedKeyUsageOids;
+ private String errorMessage = "";
+
///
/// Create new
///
@@ -87,6 +97,7 @@ public override bool ExistsInCertificate(IX509Certificate certificate) {
{
if (certificate.GetExtendedKeyUsage() == null)
{
+ errorMessage = NO_EXTENDED_KEY_USAGES_WERE_FOUND;
return false;
}
@@ -95,14 +106,24 @@ public override bool ExistsInCertificate(IX509Certificate certificate) {
providedExtendedKeyUsage.Add(singleExtendedKeyUsage);
}
}
- catch (AbstractCertificateParsingException) {
+ catch (Exception e) {
+ errorMessage = ERROR_OCCURRED_DURING_RETRIEVAL + e.GetType().Name + " " + e.Message;
return false;
}
- catch (Exception) {
- return false;
+ if (providedExtendedKeyUsage.Contains(ANY_EXTENDED_KEY_USAGE_OID) || new HashSet(providedExtendedKeyUsage
+ ).ContainsAll(extendedKeyUsageOids)) {
+ return true;
+ }
+ StringBuilder sb = new StringBuilder(ACTUAL);
+ char sep = '(';
+ foreach (String usage in providedExtendedKeyUsage)
+ {
+ sb.Append(sep).Append(usage);
+ sep = ',';
}
- return providedExtendedKeyUsage.Contains(ANY_EXTENDED_KEY_USAGE_OID) || new HashSet(providedExtendedKeyUsage
- ).ContainsAll(extendedKeyUsageOids);
+ sb.Append(')');
+ errorMessage = sb.ToString();
+ return false;
}
private static IDerObjectIdentifier[] CreateKeyPurposeIds(IList extendedKeyUsageOids) {
@@ -112,5 +133,20 @@ private static IDerObjectIdentifier[] CreateKeyPurposeIds(IList extended
}
return keyPurposeIds;
}
+
+
+ public override String GetMessage()
+ {
+ StringBuilder sb = new StringBuilder(EXPECTED_KEY_USAGES);
+ char sep = '(';
+ foreach (String usage in extendedKeyUsageOids)
+ {
+ sb.Append(sep).Append(usage);
+ sep = ',';
+ }
+ sb.Append(')');
+ sb.Append(errorMessage);
+ return sb.ToString();
+ }
}
}
diff --git a/itext/itext.sign/itext/signatures/validation/extensions/KeyUsageExtension.cs b/itext/itext.sign/itext/signatures/validation/extensions/KeyUsageExtension.cs
index 5d395b0346..28fcb8487a 100644
--- a/itext/itext.sign/itext/signatures/validation/extensions/KeyUsageExtension.cs
+++ b/itext/itext.sign/itext/signatures/validation/extensions/KeyUsageExtension.cs
@@ -20,11 +20,14 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
+using System;
using System.Collections.Generic;
+using System.Text;
using iText.Bouncycastleconnector;
using iText.Commons.Bouncycastle;
using iText.Commons.Bouncycastle.Cert;
using iText.Commons.Utils;
+using iText.IO.Util;
using iText.Kernel.Crypto;
namespace iText.Signatures.Validation.Extensions {
@@ -32,10 +35,20 @@ namespace iText.Signatures.Validation.Extensions {
public class KeyUsageExtension : CertificateExtension {
private static readonly IBouncyCastleFactory FACTORY = BouncyCastleFactoryCreator.GetFactory();
+ public const String EXPECTED_VALUE = "Key usage expected: ({0})";
+
+ public const String ACTUAL_VALUE = "\nbut found {0}";
+
+ public const String MISSING_VALUE = "\nbut nothing found.";
+
private readonly int keyUsage;
private readonly bool resultOnMissingExtension;
+ private String messagePreAmble;
+
+ private String message;
+
///
/// Create new
///
@@ -47,6 +60,10 @@ public class KeyUsageExtension : CertificateExtension {
///
/// int
/// flag which represents bit values for key usage value
+ /// bit strings are stored with the big-endian byte order and padding on the end,
+ /// the big endian notation causes a shift in actual integer values for
+ /// bits 1-8 becoming 0-7 and bit 1
+ /// the 7 bits padding makes for bit 0 to become bit 7 of the first byte
///
public KeyUsageExtension(int keyUsage)
: this(keyUsage, false) {
@@ -63,6 +80,10 @@ public KeyUsageExtension(int keyUsage)
///
/// int
/// flag which represents bit values for key usage value
+ /// bit strings are stored with the big-endian byte order and padding on the end,
+ /// the big endian notation causes a shift in actual integer values for bits 1-8
+ /// becoming 0-7 and bit 1
+ /// the 7 bits padding makes for bit 0 to become bit 7 of the first byte
///
///
/// parameter which represents return value for
@@ -73,6 +94,8 @@ public KeyUsageExtension(int keyUsage, bool resultOnMissingExtension)
: base(OID.X509Extensions.KEY_USAGE, FACTORY.CreateKeyUsage(keyUsage).ToASN1Primitive()) {
this.keyUsage = keyUsage;
this.resultOnMissingExtension = resultOnMissingExtension;
+ messagePreAmble = MessageFormatUtil.Format(EXPECTED_VALUE, ConvertKeyUsageMaskToString(keyUsage));
+ message = messagePreAmble;
}
///
@@ -164,37 +187,62 @@ public override bool ExistsInCertificate(IX509Certificate certificate) {
bool[] providedKeyUsageFlags = certificate.GetKeyUsage();
if (providedKeyUsageFlags == null) {
// By default, we want to return true if extension is not specified. Configurable.
+ message = messagePreAmble + MISSING_VALUE;
return resultOnMissingExtension;
}
- for (int i = 0; i < providedKeyUsageFlags.Length; ++i) {
- int power = providedKeyUsageFlags.Length - i - 2;
- if (power < 0) {
- // Bits are encoded backwards, for the last bit power is -1 and in this case we need to go over byte
- power = 16 + power;
- }
- if ((keyUsage & (1 << power)) != 0 && !providedKeyUsageFlags[i]) {
- return false;
+ int bitmap = 0;
+ // bit strings are stored with the big-endian byte order and padding on the end,
+ // the big endian notation causes a shift in actual integer values for bits 1-8 becoming 0-7 and bit 1
+ // the 7 bits padding makes for bit 0 to become bit 7 of the first byte
+ for (int i = 0; i < providedKeyUsageFlags.Length - 1; ++i) {
+ if (providedKeyUsageFlags[i]) {
+ bitmap += 1 << (8 - i - 1);
}
}
+ if (providedKeyUsageFlags[8]) {
+ bitmap += 0x8000;
+ }
+ if ((bitmap & keyUsage) != keyUsage) {
+ message = new StringBuilder(messagePreAmble).Append(MessageFormatUtil.Format(ACTUAL_VALUE, ConvertKeyUsageMaskToString
+ (bitmap))).ToString();
+ return false;
+ }
return true;
}
- private static int ConvertKeyUsageSetToInt(IList keyUsages) {
- KeyUsage[] possibleKeyUsage = new KeyUsage[] { KeyUsage.DIGITAL_SIGNATURE, KeyUsage.NON_REPUDIATION, KeyUsage
- .KEY_ENCIPHERMENT, KeyUsage.DATA_ENCIPHERMENT, KeyUsage.KEY_AGREEMENT, KeyUsage.KEY_CERT_SIGN, KeyUsage
- .CRL_SIGN, KeyUsage.ENCIPHER_ONLY, KeyUsage.DECIPHER_ONLY };
- int result = 0;
- for (int i = 0; i < possibleKeyUsage.Length; ++i) {
- if (keyUsages.Contains(possibleKeyUsage[i])) {
- int power = possibleKeyUsage.Length - i - 2;
- if (power < 0) {
- // Bits are encoded backwards, for the last bit power is -1 and in this case we need to go over byte
- power = 16 + power;
- }
- result |= (1 << power);
+ public override String GetMessage() {
+ return message;
+ }
+
+ private static String ConvertKeyUsageMaskToString(int keyUsageMask) {
+ StringBuilder result = new StringBuilder();
+ String separator = "";
+ // bit strings are stored with the big-endian byte order and padding on the end,
+ // the big endian notation causes a shift in actual integer values for bits 1-8 becoming 0-7 and bit 1
+ // the 7 bits padding makes for bit 0 to become bit 7 of the first byte
+ foreach (KeyUsage usage in EnumUtil.GetAllValuesOfEnum()) {
+ if (((1 << (8 - (int)(usage) - 1)) & keyUsageMask) > 0 || (usage == KeyUsage.DECIPHER_ONLY && (keyUsageMask
+ & 0x8000) == 0x8000)) {
+ result.Append(separator).Append(usage);
+ separator = ", ";
+ }
+ }
+ return result.ToString();
+ }
+
+ private static int ConvertKeyUsageSetToInt(IEnumerable keyUsages) {
+ int keyUsageMask = 0;
+ // bit strings are stored with the big-endian byte order and padding on the end,
+ // the big endian notation causes a shift in actual integer values for bits 1-8 becoming 0-7 and bit 1
+ // the 7 bits padding makes for bit 0 to become bit 7 of the first byte
+ foreach (KeyUsage usage in keyUsages) {
+ if (usage == KeyUsage.DECIPHER_ONLY) {
+ keyUsageMask += 0x8000;
+ continue;
}
+ keyUsageMask += 1 << (8 - (int)(usage) - 1);
}
- return result;
+ return keyUsageMask;
}
}
}
diff --git a/port-hash b/port-hash
index c0b8b7a280..1807f083b9 100644
--- a/port-hash
+++ b/port-hash
@@ -1 +1 @@
-36ee4b7f5a3987a868387cefea6cf91710492010
+b4fc4fb9e7cbd1c4d6129c35bab7907db3622616