All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.tencent.kona.sun.security.pkcs.SignerInfo Maven / Gradle / Ivy

Go to download

A Java security provider for supporting ShangMi algorithms in public key infrastructure

There is a newer version: 1.0.15
Show newest version
/*
 * Copyright (c) 1996, 2023, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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 General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.tencent.kona.sun.security.pkcs;

import java.io.IOException;
import java.math.BigInteger;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.CertPath;
import java.security.cert.X509Certificate;
import java.security.*;
import java.security.spec.PSSParameterSpec;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import com.tencent.kona.crypto.CryptoInsts;
import com.tencent.kona.pkix.PKIXInsts;
import com.tencent.kona.sun.security.timestamp.TimestampToken;
import com.tencent.kona.sun.security.util.Debug;
import com.tencent.kona.sun.security.util.DerEncoder;
import com.tencent.kona.sun.security.util.DerInputStream;
import com.tencent.kona.sun.security.util.DerOutputStream;
import com.tencent.kona.sun.security.util.DerValue;
import com.tencent.kona.sun.security.util.DisabledAlgorithmConstraints;
import com.tencent.kona.sun.security.util.HexDumpEncoder;
import com.tencent.kona.sun.security.util.KeyUtil;
import com.tencent.kona.sun.security.util.KnownOIDs;
import com.tencent.kona.sun.security.util.ObjectIdentifier;
import com.tencent.kona.sun.security.util.Oid;
import com.tencent.kona.sun.security.util.SignatureUtil;
import com.tencent.kona.sun.security.x509.AlgorithmId;
import com.tencent.kona.sun.security.x509.KeyUsageExtension;
import com.tencent.kona.sun.security.x509.X500Name;

/**
 * A SignerInfo, as defined in PKCS#7's signedData type.
 *
 * @author Benjamin Renaud
 */
public class SignerInfo implements DerEncoder {

    private static final DisabledAlgorithmConstraints JAR_DISABLED_CHECK =
            DisabledAlgorithmConstraints.jarConstraints();

    BigInteger version;
    X500Name issuerName;
    BigInteger certificateSerialNumber;
    AlgorithmId digestAlgorithmId;
    AlgorithmId digestEncryptionAlgorithmId;
    byte[] encryptedDigest;
    Timestamp timestamp;
    private boolean hasTimestamp = true;
    private static final Debug debug = Debug.getInstance("jar");

    PKCS9Attributes authenticatedAttributes;
    PKCS9Attributes unauthenticatedAttributes;

    /**
     * A map containing the algorithms in this SignerInfo. This is used to
     * avoid checking algorithms to see if they are disabled more than once.
     * The key is the AlgorithmId of the algorithm, and the value is a record
     * containing the name of the field or attribute and whether the key
     * should also be checked (ex: if it is a signature algorithm).
     */
    private static class AlgorithmInfo {

        private final String field;
        private final boolean checkKey;

        AlgorithmInfo(String field, boolean checkKey) {
            this.field = field;
            this.checkKey = checkKey;
        }
    }
    private final Map algorithms = new HashMap<>();

    public SignerInfo(X500Name  issuerName,
                      BigInteger serial,
                      AlgorithmId digestAlgorithmId,
                      AlgorithmId digestEncryptionAlgorithmId,
                      byte[] encryptedDigest) {
        this(issuerName, serial, digestAlgorithmId, null,
                digestEncryptionAlgorithmId, encryptedDigest, null);
    }

    public SignerInfo(X500Name  issuerName,
                      BigInteger serial,
                      AlgorithmId digestAlgorithmId,
                      PKCS9Attributes authenticatedAttributes,
                      AlgorithmId digestEncryptionAlgorithmId,
                      byte[] encryptedDigest,
                      PKCS9Attributes unauthenticatedAttributes) {
        this.version = BigInteger.ONE;
        this.issuerName = issuerName;
        this.certificateSerialNumber = serial;
        this.digestAlgorithmId = digestAlgorithmId;
        this.authenticatedAttributes = authenticatedAttributes;
        this.digestEncryptionAlgorithmId = digestEncryptionAlgorithmId;
        this.encryptedDigest = encryptedDigest;
        this.unauthenticatedAttributes = unauthenticatedAttributes;
    }

    /**
     * Parses a PKCS#7 signer info.
     */
    public SignerInfo(DerInputStream derin) throws IOException {
        this(derin, false);
    }

    /**
     * Parses a PKCS#7 signer info.
     *
     * 

This constructor is used only for backwards compatibility with * PKCS#7 blocks that were generated using JDK1.1.x. * * @param derin the ASN.1 encoding of the signer info. * @param oldStyle flag indicating whether the given signer info * is encoded according to JDK1.1.x. */ public SignerInfo(DerInputStream derin, boolean oldStyle) throws IOException { // version version = derin.getBigInteger(); // issuerAndSerialNumber DerValue[] issuerAndSerialNumber = derin.getSequence(2); if (issuerAndSerialNumber.length != 2) { throw new ParsingException("Invalid length for IssuerAndSerialNumber"); } byte[] issuerBytes = issuerAndSerialNumber[0].toByteArray(); issuerName = new X500Name(new DerValue(DerValue.tag_Sequence, issuerBytes)); certificateSerialNumber = issuerAndSerialNumber[1].getBigInteger(); // digestAlgorithmId DerValue tmp = derin.getDerValue(); digestAlgorithmId = AlgorithmId.parse(tmp); // authenticatedAttributes if (oldStyle) { // In JDK1.1.x, the authenticatedAttributes are always present, // encoded as an empty Set (Set of length zero) derin.getSet(0); } else { // check if set of auth attributes (implicit tag) is provided // (auth attributes are OPTIONAL) if ((byte)(derin.peekByte()) == (byte)0xA0) { authenticatedAttributes = new PKCS9Attributes(derin); } } // digestEncryptionAlgorithmId - little RSA naming scheme - // signature == encryption... tmp = derin.getDerValue(); digestEncryptionAlgorithmId = AlgorithmId.parse(tmp); // encryptedDigest encryptedDigest = derin.getOctetString(); // unauthenticatedAttributes if (oldStyle) { // In JDK1.1.x, the unauthenticatedAttributes are always present, // encoded as an empty Set (Set of length zero) derin.getSet(0); } else { // check if set of unauth attributes (implicit tag) is provided // (unauth attributes are OPTIONAL) if (derin.available() != 0 && (byte)(derin.peekByte()) == (byte)0xA1) { unauthenticatedAttributes = new PKCS9Attributes(derin, true);// ignore unsupported attrs } } // all done if (derin.available() != 0) { throw new ParsingException("extra data at the end"); } // verify CMSAlgorithmProtection checkCMSAlgorithmProtection(); } // CMSAlgorithmProtection verification as described in RFC 6211 private void checkCMSAlgorithmProtection() throws IOException { if (authenticatedAttributes == null) { return; } PKCS9Attribute ap = authenticatedAttributes.getAttribute( PKCS9Attribute.CMS_ALGORITHM_PROTECTION_OID); if (ap == null) { return; } DerValue dv = new DerValue((byte[])ap.getValue()); DerInputStream data = dv.getData(); AlgorithmId d = AlgorithmId.parse(data.getDerValue()); DerValue ds = data.getDerValue(); if (data.available() > 0) { throw new IOException("Unknown field in CMSAlgorithmProtection"); } if (!ds.isContextSpecific((byte)1)) { throw new IOException("No signature algorithm in CMSAlgorithmProtection"); } AlgorithmId s = AlgorithmId.parse(ds.withTag(DerValue.tag_Sequence)); if (!s.equals(digestEncryptionAlgorithmId) || !d.equals(digestAlgorithmId)) { throw new IOException("CMSAlgorithmProtection check failed"); } } /** * DER encode this object onto an output stream. * Implements the {@code DerEncoder} interface. * * @param out * the output stream on which to write the DER encoding. */ @Override public void encode(DerOutputStream out) { DerOutputStream seq = new DerOutputStream(); seq.putInteger(version); DerOutputStream issuerAndSerialNumber = new DerOutputStream(); issuerName.encode(issuerAndSerialNumber); issuerAndSerialNumber.putInteger(certificateSerialNumber); seq.write(DerValue.tag_Sequence, issuerAndSerialNumber); digestAlgorithmId.encode(seq); // encode authenticated attributes if there are any if (authenticatedAttributes != null) authenticatedAttributes.encode((byte)0xA0, seq); digestEncryptionAlgorithmId.encode(seq); seq.putOctetString(encryptedDigest); // encode unauthenticated attributes if there are any if (unauthenticatedAttributes != null) unauthenticatedAttributes.encode((byte)0xA1, seq); out.write(DerValue.tag_Sequence, seq); } /* * Returns the (user) certificate pertaining to this SignerInfo. */ public X509Certificate getCertificate(PKCS7 block) throws IOException { return block.getCertificate(certificateSerialNumber, issuerName); } /* * Returns the certificate chain pertaining to this SignerInfo. */ public ArrayList getCertificateChain(PKCS7 block) throws IOException { X509Certificate userCert; userCert = block.getCertificate(certificateSerialNumber, issuerName); if (userCert == null) return null; ArrayList certList = new ArrayList<>(); certList.add(userCert); X509Certificate[] pkcsCerts = block.getCertificates(); if (pkcsCerts == null || userCert.getSubjectX500Principal().equals(userCert.getIssuerX500Principal())) { return certList; } Principal issuer = userCert.getIssuerX500Principal(); int start = 0; while (true) { boolean match = false; int i = start; while (i < pkcsCerts.length) { if (issuer.equals(pkcsCerts[i].getSubjectX500Principal())) { // next cert in chain found certList.add(pkcsCerts[i]); // if selected cert is self-signed, we're done // constructing the chain if (pkcsCerts[i].getSubjectX500Principal().equals( pkcsCerts[i].getIssuerX500Principal())) { start = pkcsCerts.length; } else { issuer = pkcsCerts[i].getIssuerX500Principal(); X509Certificate tmpCert = pkcsCerts[start]; pkcsCerts[start] = pkcsCerts[i]; pkcsCerts[i] = tmpCert; start++; } match = true; break; } else { i++; } } if (!match) break; } return certList; } /* Returns null if verify fails, this signerInfo if verify succeeds. */ SignerInfo verify(PKCS7 block, byte[] data) throws NoSuchAlgorithmException, SignatureException { try { Timestamp timestamp = null; try { timestamp = getTimestamp(); } catch (Exception e) { // Log exception and continue. This allows for the case // where, if there are no other errors, the code is // signed but w/o a timestamp. if (debug != null) { debug.println("Unexpected exception while getting" + " timestamp: " + e); } } ContentInfo content = block.getContentInfo(); if (data == null) { data = content.getContentBytes(); } String digestAlgName = digestAlgorithmId.getName(); algorithms.put(digestAlgorithmId, new AlgorithmInfo("SignerInfo digestAlgorithm field", false)); byte[] dataSigned; // if there are authenticated attributes, get the message // digest and compare it with the digest of data if (authenticatedAttributes == null) { dataSigned = data; } else { // first, check content type ObjectIdentifier contentType = (ObjectIdentifier) authenticatedAttributes.getAttributeValue( PKCS9Attribute.CONTENT_TYPE_OID); if (contentType == null || !contentType.equals((Object) content.contentType)) return null; // contentType does not match, bad SignerInfo // now, check message digest byte[] messageDigest = (byte[]) authenticatedAttributes.getAttributeValue( PKCS9Attribute.MESSAGE_DIGEST_OID); if (messageDigest == null) // fail if there is no message digest return null; MessageDigest md = CryptoInsts.getMessageDigest(digestAlgName); byte[] computedMessageDigest = md.digest(data); if (!MessageDigest.isEqual(messageDigest, computedMessageDigest)) { return null; } // message digest attribute matched // digest of original data // the data actually signed is the DER encoding of // the authenticated attributes (tagged with // the "SET OF" tag, not 0xA0). dataSigned = authenticatedAttributes.getDerEncoding(); } // put together digest algorithm and encryption algorithm // to form signing algorithm. See makeSigAlg for details. String sigAlgName = makeSigAlg( digestAlgorithmId, digestEncryptionAlgorithmId); KnownOIDs oid = KnownOIDs.findMatch(sigAlgName); if (oid != null) { AlgorithmId sigAlgId = new AlgorithmId(Oid.of(oid), digestEncryptionAlgorithmId.getParameters()); algorithms.put(sigAlgId, new AlgorithmInfo( "SignerInfo digestEncryptionAlgorithm field", true)); } X509Certificate cert = getCertificate(block); if (cert == null) { return null; } PublicKey key = cert.getPublicKey(); if (cert.hasUnsupportedCriticalExtension()) { throw new SignatureException("Certificate has unsupported " + "critical extension(s)"); } algorithmsConformanceCheck( digestAlgorithmId, digestEncryptionAlgorithmId, key, authenticatedAttributes == null); // Make sure that if the usage of the key in the certificate is // restricted, it can be used for digital signatures. // XXX We may want to check for additional extensions in the // future. boolean[] keyUsageBits = cert.getKeyUsage(); if (keyUsageBits != null) { KeyUsageExtension keyUsage; // We don't care whether this extension was marked // critical in the certificate. // We're interested only in its value (i.e., the bits set) // and treat the extension as critical. keyUsage = new KeyUsageExtension(keyUsageBits); boolean digSigAllowed = keyUsage.get(KeyUsageExtension.DIGITAL_SIGNATURE); boolean nonRepuAllowed = keyUsage.get(KeyUsageExtension.NON_REPUDIATION); if (!digSigAllowed && !nonRepuAllowed) { throw new SignatureException("Key usage restricted: " + "cannot be used for " + "digital signatures"); } } Signature sig = CryptoInsts.getSignature(sigAlgName); AlgorithmParameters ap = digestEncryptionAlgorithmId.getParameters(); try { SignatureUtil.initVerifyWithParam(sig, key, SignatureUtil.getParamSpec(sigAlgName, ap)); } catch (ProviderException | InvalidAlgorithmParameterException | InvalidKeyException e) { throw new SignatureException(e.getMessage(), e); } sig.update(dataSigned); if (sig.verify(encryptedDigest)) { return this; } } catch (IOException e) { throw new SignatureException("Error verifying signature", e); } return null; } /** * Checks if the digest algorithm and encryption algorithm combination * inside a PKCS7 SignerInfo is legal. * * @param digAlgId the digest algorithm * @param encAlgId the encryption algorithm * @param key the public key for verification * @param directSign whether the signature is calculated on the content * directly. This makes difference for Ed448. */ private static void algorithmsConformanceCheck( AlgorithmId digAlgId, AlgorithmId encAlgId, PublicKey key, boolean directSign) throws NoSuchAlgorithmException { String encAlg = encAlgId.getName(); switch (encAlg) { case "RSASSA-PSS": PSSParameterSpec spec = (PSSParameterSpec) SignatureUtil.getParamSpec(encAlg, encAlgId.getParameters()); /* * RFC 4056 section 3 for Signed-data: * signatureAlgorithm MUST contain id-RSASSA-PSS. The algorithm * parameters field MUST contain RSASSA-PSS-params. */ if (spec == null) { throw new NoSuchAlgorithmException("Missing PSSParameterSpec for RSASSA-PSS algorithm"); } if (!AlgorithmId.get(spec.getDigestAlgorithm()).equals(digAlgId)) { throw new NoSuchAlgorithmException("Incompatible digest algorithm"); } break; // case "Ed25519": // if (!digAlgId.equals(SignatureUtil.EdDSADigestAlgHolder.sha512)) { // throw new NoSuchAlgorithmException("Incompatible digest algorithm"); // } // break; // case "Ed448": // if (directSign) { // if (!digAlgId.equals(SignatureUtil.EdDSADigestAlgHolder.shake256)) { // throw new NoSuchAlgorithmException("Incompatible digest algorithm"); // } // } else { // if (!digAlgId.equals(SignatureUtil.EdDSADigestAlgHolder.shake256$512)) { // throw new NoSuchAlgorithmException("Incompatible digest algorithm"); // } // } // break; case "HSS/LMS": // RFC 8708 requires the same hash algorithm used as in the HSS/LMS algorithm if (!digAlgId.equals(AlgorithmId.get(KeyUtil.hashAlgFromHSS(key)))) { throw new NoSuchAlgorithmException("Incompatible digest algorithm"); } break; } } /** * Derives the signature algorithm name from the digest algorithm * and the encryption algorithm inside a PKCS7 SignerInfo. * * The digest algorithm is in the form "DIG", and the encryption * algorithm can be in any of the 3 forms: * * 1. Old style key algorithm like RSA, DSA, EC, this method returns * DIGwithKEY. * 2. New style signature algorithm in the form of HASHwithKEY, this * method returns DIGwithKEY. Please note this is not HASHwithKEY. * 3. Modern signature algorithm like RSASSA-PSS and EdDSA, this method * returns the signature algorithm itself. * * @param digAlgId the digest algorithm * @param encAlgId the encryption algorithm */ public static String makeSigAlg(AlgorithmId digAlgId, AlgorithmId encAlgId) { String encAlg = encAlgId.getName(); switch (encAlg) { case "RSASSA-PSS": case "Ed25519": case "Ed448": case "HSS/LMS": return encAlg; default: String digAlg = digAlgId.getName(); String keyAlg = SignatureUtil.extractKeyAlgFromDwithE(encAlg); if (keyAlg == null) { // The encAlg used to be only the key alg keyAlg = encAlg; } if (digAlg.startsWith("SHA-")) { digAlg = "SHA" + digAlg.substring(4); } if (keyAlg.equals("EC")) keyAlg = "ECDSA"; String sigAlg = digAlg + "with" + keyAlg; try { Signature.getInstance(sigAlg); return sigAlg; } catch (NoSuchAlgorithmException e) { // Possibly an unknown modern signature algorithm, // in this case, encAlg should already be a signature // algorithm. return encAlg; } } } /* Verify the content of the pkcs7 block. */ SignerInfo verify(PKCS7 block) throws NoSuchAlgorithmException, SignatureException { return verify(block, null); } public BigInteger getVersion() { return version; } public X500Name getIssuerName() { return issuerName; } public BigInteger getCertificateSerialNumber() { return certificateSerialNumber; } public AlgorithmId getDigestAlgorithmId() { return digestAlgorithmId; } public PKCS9Attributes getAuthenticatedAttributes() { return authenticatedAttributes; } public AlgorithmId getDigestEncryptionAlgorithmId() { return digestEncryptionAlgorithmId; } public byte[] getEncryptedDigest() { return encryptedDigest; } public PKCS9Attributes getUnauthenticatedAttributes() { return unauthenticatedAttributes; } /** * Returns the timestamp PKCS7 data unverified. * @return a PKCS7 object */ public PKCS7 getTsToken() throws IOException { if (unauthenticatedAttributes == null) { return null; } PKCS9Attribute tsTokenAttr = unauthenticatedAttributes.getAttribute( PKCS9Attribute.SIGNATURE_TIMESTAMP_TOKEN_OID); if (tsTokenAttr == null) { return null; } return new PKCS7((byte[])tsTokenAttr.getValue()); } /* * Extracts a timestamp from a PKCS7 SignerInfo. * * Examines the signer's unsigned attributes for a * {@code signatureTimestampToken} attribute. If present, * then it is parsed to extract the date and time at which the * timestamp was generated. * * @param info A signer information element of a PKCS 7 block. * * @return A timestamp token or null if none is present. * @throws IOException if an error is encountered while parsing the * PKCS7 data. * @throws NoSuchAlgorithmException if an error is encountered while * verifying the PKCS7 object. * @throws SignatureException if an error is encountered while * verifying the PKCS7 object. * @throws CertificateException if an error is encountered while generating * the TSA's certpath. */ public Timestamp getTimestamp() throws IOException, NoSuchAlgorithmException, SignatureException, CertificateException { if (timestamp != null || !hasTimestamp) return timestamp; PKCS7 tsToken = getTsToken(); if (tsToken == null) { hasTimestamp = false; return null; } // Extract the content (an encoded timestamp token info) byte[] encTsTokenInfo = tsToken.getContentInfo().getData(); // Extract the signer (the Timestamping Authority) // while verifying the content SignerInfo[] tsa = tsToken.verify(encTsTokenInfo); if (tsa == null || tsa.length == 0) { throw new SignatureException("Unable to verify timestamp"); } // Expect only one signer ArrayList chain = tsa[0].getCertificateChain(tsToken); CertificateFactory cf = PKIXInsts.getCertificateFactory("X.509"); CertPath tsaChain = cf.generateCertPath(chain); // Create a timestamp token info object TimestampToken tsTokenInfo = new TimestampToken(encTsTokenInfo); // Check that the signature timestamp applies to this signature verifyTimestamp(tsTokenInfo); algorithms.putAll(tsa[0].algorithms); // Create a timestamp object timestamp = new Timestamp(tsTokenInfo.getDate(), tsaChain); return timestamp; } /* * Check that the signature timestamp applies to this signature. * Match the hash present in the signature timestamp token against the hash * of this signature. */ private void verifyTimestamp(TimestampToken token) throws NoSuchAlgorithmException, SignatureException { AlgorithmId digestAlgId = token.getHashAlgorithm(); algorithms.put(digestAlgId, new AlgorithmInfo("TimestampToken digestAlgorithm field", false)); MessageDigest md = CryptoInsts.getMessageDigest(digestAlgId.getName()); if (!MessageDigest.isEqual(token.getHashedMessage(), md.digest(encryptedDigest))) { throw new SignatureException("Signature timestamp (#" + Debug.toString(token.getSerialNumber()) + ") generated on " + token.getDate() + " is inapplicable"); } if (debug != null) { debug.println(); debug.println("Detected signature timestamp (#" + Debug.toString(token.getSerialNumber()) + ") generated on " + token.getDate()); debug.println(); } } public String toString() { HexDumpEncoder hexDump = new HexDumpEncoder(); String out = ""; out += "Signer Info for (issuer): " + issuerName + "\n"; out += "\tversion: " + Debug.toHexString(version) + "\n"; out += "\tcertificateSerialNumber: " + Debug.toHexString(certificateSerialNumber) + "\n"; out += "\tdigestAlgorithmId: " + digestAlgorithmId + "\n"; if (authenticatedAttributes != null) { out += "\tauthenticatedAttributes: " + authenticatedAttributes + "\n"; } out += "\tdigestEncryptionAlgorithmId: " + digestEncryptionAlgorithmId + "\n"; out += "\tencryptedDigest: " + "\n" + hexDump.encodeBuffer(encryptedDigest) + "\n"; if (unauthenticatedAttributes != null) { out += "\tunauthenticatedAttributes: " + unauthenticatedAttributes + "\n"; } return out; } // sun.security.util.SignatureFileVerifier invokes this method // from sun.security.pkcs.SignerInfo, but not here. // /** // * Verify all the algorithms in the array of SignerInfos against the // * constraints in the jdk.jar.disabledAlgorithms security property. // * // * @param infos array of SignerInfos // * @param params constraint parameters // * @param name the name of the signer's PKCS7 file // * @return a set of algorithms that passed the checks and are not disabled // */ // public static Set verifyAlgorithms(SignerInfo[] infos, // JarConstraintsParameters params, String name) throws SignatureException { // Map algorithms = new HashMap<>(); // for (SignerInfo info : infos) { // algorithms.putAll(info.algorithms); // } // // Set enabledAlgorithms = new HashSet<>(); // try { // for (Map.Entry algEntry // : algorithms.entrySet()) { // AlgorithmInfo info = algEntry.getValue(); // params.setExtendedExceptionMsg(name, info.field); // AlgorithmId algId = algEntry.getKey(); // JAR_DISABLED_CHECK.permits(algId.getName(), // algId.getParameters(), params, info.checkKey); // enabledAlgorithms.add(algId.getName()); // } // } catch (CertPathValidatorException e) { // throw new SignatureException(e); // } // return enabledAlgorithms; // } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy