Skip to content

Commit 5a9f02e

Browse files
eferolloromen
authored andcommitted
feat(toolkit/certviewer): Add composite ML-DSA (MLDSA65-Ed25519-SHA512) certificate support to certviewer
Signed-off-by: Francesco Rollo <eferollo@gmail.com>
1 parent 8b5d6a7 commit 5a9f02e

File tree

4 files changed

+100
-1
lines changed

4 files changed

+100
-1
lines changed

toolkit/components/certviewer/content/certDecoder.mjs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
RSAPublicKey,
1010
MLDSAPublicKey,
1111
SLHDSAPublicKey,
12+
CompositeMLDSAPublicKey,
1213
} from "./vendor/pkijs.js";
1314

1415
const getTimeZone = () => {
@@ -67,6 +68,15 @@ const getPublicKeyInfo = x509 => {
6768
rhoT1: hashify(keyHex),
6869
};
6970
}
71+
if (publicKey instanceof CompositeMLDSAPublicKey) {
72+
let keyHex = publicKey.blob.valueBlock.valueHex;
73+
let keyBytes = new Uint8Array(keyHex);
74+
return {
75+
kty: publicKey.alg,
76+
keysize: keyBytes.length,
77+
rhoT1: hashify(keyHex),
78+
};
79+
}
7080
return { kty: "Unknown" };
7181
};
7282

@@ -1163,6 +1173,7 @@ const strings = {
11631173
"2.16.840.1.101.3.4.3.29": "SLH-DSA-SHAKE-192F",
11641174
"2.16.840.1.101.3.4.3.30": "SLH-DSA-SHAKE-256S",
11651175
"2.16.840.1.101.3.4.3.31": "SLH-DSA-SHAKE-256F",
1176+
"2.16.840.1.114027.80.9.1.11": "MLDSA65-Ed25519-SHA512",
11661177
},
11671178

11681179
aia: {

toolkit/components/certviewer/content/certviewer.mjs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ const getSecurityLevel = signatureName => {
8686
case "ML-DSA-65":
8787
case "SLH-DSA-SHAKE-192S":
8888
case "SLH-DSA-SHAKE-192F":
89+
case "MLDSA65-Ed25519-SHA512":
8990
return "Level 3 (NIST)";
9091
case "ML-DSA-87":
9192
case "SLH-DSA-SHAKE-256S":
@@ -205,6 +206,11 @@ export const adjustCertInformation = cert => {
205206
cert.subjectPublicKeyInfo.seedRoot,
206207
true
207208
),
209+
createEntryItem(
210+
"composite-mldsa-public-value",
211+
cert.subjectPublicKeyInfo.blob,
212+
true
213+
),
208214
].filter(elem => elem != null);
209215
}
210216
return items;

toolkit/components/certviewer/content/vendor/pkijs.js

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8757,6 +8757,74 @@ class SLHDSAPublicKey extends PkiObject {
87578757
}
87588758
}
87598759

8760+
/*
8761+
* @see https://datatracker.ietf.org/doc/draft-ietf-lamps-pq-composite-sigs/
8762+
* Here the seriealized public key (mldsaPK, tradPK) is treated as a whole blob.
8763+
*/
8764+
const BLOB = "blob";
8765+
/* ALG is defined above */
8766+
const CLEAR_PROPS_CompositeMLDSA = [BLOB, ALG];
8767+
class CompositeMLDSAPublicKey extends PkiObject {
8768+
constructor(parameters = {}) {
8769+
super();
8770+
8771+
this.blob = getParametersValue(parameters, BLOB, CompositeMLDSAPublicKey.defaultValues(BLOB));
8772+
this.alg = getParametersValue(parameters, ALG, CompositeMLDSAPublicKey.defaultValues(ALG));
8773+
8774+
if (parameters.json) {
8775+
this.fromJSON(parameters.json);
8776+
}
8777+
8778+
if (parameters.schema) {
8779+
this.fromSchema(parameters.schema);
8780+
}
8781+
}
8782+
8783+
static defaultValues(memberName) {
8784+
switch (memberName) {
8785+
case BLOB:
8786+
return new BitString();
8787+
case ALG:
8788+
return "";
8789+
default:
8790+
return super.defaultValues(memberName);
8791+
}
8792+
}
8793+
8794+
static schema(parameters = {}) {
8795+
const names = getParametersValue(parameters, "names", {});
8796+
return new BitString({ name: names.blob || BLOB });
8797+
}
8798+
8799+
fromSchema(schema) {
8800+
clearProps(schema, CLEAR_PROPS_CompositeMLDSA);
8801+
8802+
const asn1 = compareSchema(schema, schema, CompositeMLDSAPublicKey.schema({
8803+
names: { blob: BLOB }
8804+
}));
8805+
8806+
AsnError.assertSchema(asn1, this.className);
8807+
8808+
this.blob = asn1.result.blob;
8809+
}
8810+
8811+
toSchema() {
8812+
return this.blob;
8813+
}
8814+
8815+
toJSON() {
8816+
return {
8817+
blob: Convert.ToBase64Url(this.blob.valueBlock.valueHexView),
8818+
alg: this.alg
8819+
};
8820+
}
8821+
8822+
fromJSON(json) {
8823+
ParameterError.assert("json", json, "blob");
8824+
const rawBuffer = stringToArrayBuffer(fromBase64(json.blob, true));
8825+
this.blob = new BitString({ valueHex: rawBuffer });
8826+
}
8827+
}
87608828

87618829
const ALGORITHM$1 = "algorithm";
87628830
const SUBJECT_PUBLIC_KEY = "subjectPublicKey";
@@ -8842,6 +8910,9 @@ class PublicKeyInfo extends PkiObject {
88428910
/* Already a bitstring */
88438911
this._parsedKey = new SLHDSAPublicKey({ seedRoot: this.subjectPublicKey, alg: "SLH-DSA-SHAKE-256F" });
88448912
break;
8913+
case "2.16.840.1.114027.80.9.1.11":
8914+
this._parsedKey = new CompositeMLDSAPublicKey({ blob: this.subjectPublicKey, alg: "MLDSA65-Ed25519-SHA512" });
8915+
break;
88458916
}
88468917
this._parsedKey || (this._parsedKey = null);
88478918
}
@@ -8936,6 +9007,9 @@ class PublicKeyInfo extends PkiObject {
89369007
case "2.16.840.1.101.3.4.3.31":
89379008
jwk.kty = "SLH-DSA-SHAKE-256F";
89389009
break;
9010+
case "2.16.840.1.114027.80.9.1.11":
9011+
jwk.kty = "MLDSA65-Ed25519-SHA512";
9012+
break;
89399013
}
89409014
const publicKeyJWK = this.parsedKey.toJSON();
89419015
Object.assign(jwk, publicKeyJWK);
@@ -9021,6 +9095,13 @@ class PublicKeyInfo extends PkiObject {
90219095
algorithmParams: new Null()
90229096
});
90239097
break;
9098+
case "MLDSA65-Ed25519-SHA512":
9099+
this.parsedKey = new CompositeMLDSAPublicKey({ json });
9100+
this.algorithm = new AlgorithmIdentifier({
9101+
algorithmId: "2.16.840.1.114027.80.9.1.11",
9102+
algorithmParams: new Null()
9103+
});
9104+
break;
90249105
default:
90259106
throw new Error(`Invalid value for "kty" parameter: ${json.kty}`);
90269107
}
@@ -24353,4 +24434,4 @@ function initCryptoEngine() {
2435324434

2435424435
initCryptoEngine();
2435524436

24356-
export { AbstractCryptoEngine, AccessDescription, Accuracy, AlgorithmIdentifier, AltName, ArgumentError, AsnError, AttCertValidityPeriod, Attribute, AttributeCertificateInfoV1, AttributeCertificateInfoV2, AttributeCertificateV1, AttributeCertificateV2, AttributeTypeAndValue, AuthenticatedSafe, AuthorityKeyIdentifier, BasicConstraints, BasicOCSPResponse, CAVersion, CRLBag, CRLDistributionPoints, CertBag, CertID, Certificate, CertificateChainValidationEngine, CertificatePolicies, CertificateRevocationList, CertificateSet, CertificateTemplate, CertificationRequest, ChainValidationCode, ChainValidationError, ContentInfo, CryptoEngine, DigestInfo, DistributionPoint, ECCCMSSharedInfo, ECNamedCurves, ECPrivateKey, ECPublicKey, EncapsulatedContentInfo, EncryptedContentInfo, EncryptedData, EnvelopedData, ExtKeyUsage, Extension, ExtensionValueFactory, Extensions, GeneralName, GeneralNames, GeneralSubtree, HASHED_MESSAGE, HASH_ALGORITHM, Holder, InfoAccess, IssuerAndSerialNumber, IssuerSerial, IssuingDistributionPoint, KEKIdentifier, KEKRecipientInfo, KeyAgreeRecipientIdentifier, KeyAgreeRecipientInfo, KeyBag, KeyTransRecipientInfo, MICROS, MILLIS, MacData, MessageImprint, NameConstraints, OCSPRequest, OCSPResponse, ObjectDigestInfo, OriginatorIdentifierOrKey, OriginatorInfo, OriginatorPublicKey, OtherCertificateFormat, OtherKeyAttribute, OtherPrimeInfo, OtherRecipientInfo, OtherRevocationInfoFormat, PBES2Params, PBKDF2Params, PFX, PKCS8ShroudedKeyBag, PKIStatus, PKIStatusInfo, POLICY_IDENTIFIER, POLICY_QUALIFIERS, ParameterError, PasswordRecipientinfo, PkiObject, PolicyConstraints, PolicyInformation, PolicyMapping, PolicyMappings, PolicyQualifierInfo, PrivateKeyInfo, PrivateKeyUsagePeriod, PublicKeyInfo, QCStatement, QCStatements, RDN, RSAESOAEPParams, RSAPrivateKey, RSAPublicKey, RSASSAPSSParams, RecipientEncryptedKey, RecipientEncryptedKeys, RecipientIdentifier, RecipientInfo, RecipientKeyIdentifier, RelativeDistinguishedNames, Request, ResponseBytes, ResponseData, RevocationInfoChoices, RevokedCertificate, SECONDS, SafeBag, SafeBagValueFactory, SafeContents, SecretBag, Signature, SignedAndUnsignedAttributes, SignedCertificateTimestamp, SignedCertificateTimestampList, SignedData, SignedDataVerifyError, SignerInfo, SingleResponse, SubjectDirectoryAttributes, TBSRequest, TSTInfo, TYPE$4 as TYPE, TYPE_AND_VALUES, Time, TimeStampReq, TimeStampResp, TimeType, V2Form, VALUE$5 as VALUE, VALUE_BEFORE_DECODE, checkCA, createCMSECDSASignature, createECDSASignatureFromCMS, engine, getAlgorithmByOID, getAlgorithmParameters, getCrypto, getEngine, getHashAlgorithm, getOIDByAlgorithm, getRandomValues, id_AnyPolicy, id_AuthorityInfoAccess, id_AuthorityKeyIdentifier, id_BaseCRLNumber, id_BasicConstraints, id_CRLBag_X509CRL, id_CRLDistributionPoints, id_CRLNumber, id_CRLReason, id_CertBag_AttributeCertificate, id_CertBag_SDSICertificate, id_CertBag_X509Certificate, id_CertificateIssuer, id_CertificatePolicies, id_ContentType_Data, id_ContentType_EncryptedData, id_ContentType_EnvelopedData, id_ContentType_SignedData, id_ExtKeyUsage, id_FreshestCRL, id_InhibitAnyPolicy, id_InvalidityDate, id_IssuerAltName, id_IssuingDistributionPoint, id_KeyUsage, id_MicrosoftAppPolicies, id_MicrosoftCaVersion, id_MicrosoftCertTemplateV1, id_MicrosoftCertTemplateV2, id_MicrosoftPrevCaCertHash, id_NameConstraints, id_PKIX_OCSP_Basic, id_PolicyConstraints, id_PolicyMappings, id_PrivateKeyUsagePeriod, id_QCStatements, id_SignedCertificateTimestampList, id_SubjectAltName, id_SubjectDirectoryAttributes, id_SubjectInfoAccess, id_SubjectKeyIdentifier, id_ad, id_ad_caIssuers, id_ad_ocsp, id_eContentType_TSTInfo, id_pkix, id_sha1, id_sha256, id_sha384, id_sha512, kdf, setEngine, stringPrep, verifySCTsForCertificate, MLDSAPublicKey, SLHDSAPublicKey };
24437+
export { AbstractCryptoEngine, AccessDescription, Accuracy, AlgorithmIdentifier, AltName, ArgumentError, AsnError, AttCertValidityPeriod, Attribute, AttributeCertificateInfoV1, AttributeCertificateInfoV2, AttributeCertificateV1, AttributeCertificateV2, AttributeTypeAndValue, AuthenticatedSafe, AuthorityKeyIdentifier, BasicConstraints, BasicOCSPResponse, CAVersion, CRLBag, CRLDistributionPoints, CertBag, CertID, Certificate, CertificateChainValidationEngine, CertificatePolicies, CertificateRevocationList, CertificateSet, CertificateTemplate, CertificationRequest, ChainValidationCode, ChainValidationError, ContentInfo, CryptoEngine, DigestInfo, DistributionPoint, ECCCMSSharedInfo, ECNamedCurves, ECPrivateKey, ECPublicKey, EncapsulatedContentInfo, EncryptedContentInfo, EncryptedData, EnvelopedData, ExtKeyUsage, Extension, ExtensionValueFactory, Extensions, GeneralName, GeneralNames, GeneralSubtree, HASHED_MESSAGE, HASH_ALGORITHM, Holder, InfoAccess, IssuerAndSerialNumber, IssuerSerial, IssuingDistributionPoint, KEKIdentifier, KEKRecipientInfo, KeyAgreeRecipientIdentifier, KeyAgreeRecipientInfo, KeyBag, KeyTransRecipientInfo, MICROS, MILLIS, MacData, MessageImprint, NameConstraints, OCSPRequest, OCSPResponse, ObjectDigestInfo, OriginatorIdentifierOrKey, OriginatorInfo, OriginatorPublicKey, OtherCertificateFormat, OtherKeyAttribute, OtherPrimeInfo, OtherRecipientInfo, OtherRevocationInfoFormat, PBES2Params, PBKDF2Params, PFX, PKCS8ShroudedKeyBag, PKIStatus, PKIStatusInfo, POLICY_IDENTIFIER, POLICY_QUALIFIERS, ParameterError, PasswordRecipientinfo, PkiObject, PolicyConstraints, PolicyInformation, PolicyMapping, PolicyMappings, PolicyQualifierInfo, PrivateKeyInfo, PrivateKeyUsagePeriod, PublicKeyInfo, QCStatement, QCStatements, RDN, RSAESOAEPParams, RSAPrivateKey, RSAPublicKey, RSASSAPSSParams, RecipientEncryptedKey, RecipientEncryptedKeys, RecipientIdentifier, RecipientInfo, RecipientKeyIdentifier, RelativeDistinguishedNames, Request, ResponseBytes, ResponseData, RevocationInfoChoices, RevokedCertificate, SECONDS, SafeBag, SafeBagValueFactory, SafeContents, SecretBag, Signature, SignedAndUnsignedAttributes, SignedCertificateTimestamp, SignedCertificateTimestampList, SignedData, SignedDataVerifyError, SignerInfo, SingleResponse, SubjectDirectoryAttributes, TBSRequest, TSTInfo, TYPE$4 as TYPE, TYPE_AND_VALUES, Time, TimeStampReq, TimeStampResp, TimeType, V2Form, VALUE$5 as VALUE, VALUE_BEFORE_DECODE, checkCA, createCMSECDSASignature, createECDSASignatureFromCMS, engine, getAlgorithmByOID, getAlgorithmParameters, getCrypto, getEngine, getHashAlgorithm, getOIDByAlgorithm, getRandomValues, id_AnyPolicy, id_AuthorityInfoAccess, id_AuthorityKeyIdentifier, id_BaseCRLNumber, id_BasicConstraints, id_CRLBag_X509CRL, id_CRLDistributionPoints, id_CRLNumber, id_CRLReason, id_CertBag_AttributeCertificate, id_CertBag_SDSICertificate, id_CertBag_X509Certificate, id_CertificateIssuer, id_CertificatePolicies, id_ContentType_Data, id_ContentType_EncryptedData, id_ContentType_EnvelopedData, id_ContentType_SignedData, id_ExtKeyUsage, id_FreshestCRL, id_InhibitAnyPolicy, id_InvalidityDate, id_IssuerAltName, id_IssuingDistributionPoint, id_KeyUsage, id_MicrosoftAppPolicies, id_MicrosoftCaVersion, id_MicrosoftCertTemplateV1, id_MicrosoftCertTemplateV2, id_MicrosoftPrevCaCertHash, id_NameConstraints, id_PKIX_OCSP_Basic, id_PolicyConstraints, id_PolicyMappings, id_PrivateKeyUsagePeriod, id_QCStatements, id_SignedCertificateTimestampList, id_SubjectAltName, id_SubjectDirectoryAttributes, id_SubjectInfoAccess, id_SubjectKeyIdentifier, id_ad, id_ad_caIssuers, id_ad_ocsp, id_eContentType_TSTInfo, id_pkix, id_sha1, id_sha256, id_sha384, id_sha512, kdf, setEngine, stringPrep, verifySCTsForCertificate, MLDSAPublicKey, SLHDSAPublicKey, CompositeMLDSAPublicKey };

toolkit/locales/en-US/toolkit/about/certviewer.ftl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ certificate-viewer-protocol = Protocol
4949
certificate-viewer-public-value = Public Value
5050
certificate-viewer-mldsa-public-value = Public Value
5151
certificate-viewer-slhdsa-public-value = Public Value
52+
certificate-viewer-composite-mldsa-public-value = Public Value
5253
certificate-viewer-purposes = Purposes
5354
certificate-viewer-qualifier = Qualifier
5455
certificate-viewer-qualifiers = Qualifiers

0 commit comments

Comments
 (0)