[JAVA] Certificat électronique ceci et cela

Chose que tu veux faire

Comme il s'agit de la première implémentation de la signature XML, j'ai décidé de continuer en laissant diverses notes.

--Je veux signer XML en Java

Opération

  1. Importez le certificat au format PKCS12 (.p12) dans le magasin de clés Java (cacert)
  2. Modifiez chaque paramètre obtenu à partir de la base de données (si nécessaire)
    chemin cacert, mot de passe du keystore, alias, algorithme de chiffrement, algorithme de résumé, algorithme de signature, etc. .. ..

L'opération ci-dessus est requise chaque fois que le certificat électronique est remplacé.

Ce qu'il faut chercher

Qu'est-ce qu'un certificat électronique? ??

Qu'est-ce que la «normalisation» des certificats électroniques? http://www.atmarkit.co.jp/fxml/tanpatsu/16xmlsecurity/xmlsecurity02.html

À propos du format de fichier de clé et de certificat RSA https://qiita.com/kunichiko/items/12cbccaadcbf41c72735

Extraire la clé privée, le certificat et l'autorité de certification intermédiaire du fichier PKCS # 12 https://qiita.com/cs_sonar/items/f2753ffdebb1c67d5302

Comment créer un certificat auto-signé https://qiita.com/akito1986/items/8eb41f5a43bb9421ae79

Comment faire une signature XML en Java? ??

Signature XML à l'aide de l'API de signature numérique XML de Java http://qiita.com/KevinFQ/items/4e2484a659b618530e72

liste de commandes keytool http://itref.fc2web.com/java/keytool.html

[Java] Ajouter / supprimer des certificats du magasin de clés en Java https://blogs.yahoo.co.jp/dk521123/37097725.html

Diverses notes

Convertir du certificat de serveur pem en crt

$ openssl x509 -outform der in server-crt.pem -out server-crt.crt

Conversion du certificat de serveur pem en p12

$ openssl pkcs12 -export -out server-crt.p12 -in server-crt.pem -inkey server-privatekey.pem -passin pass:root -passout pass:root

Certificat serveur p12 ⇒ Convertir en crt

$ openssl pkcs12 -in server-crt.p12 -clcerts -nokeys -out server-crt.crt

Certificat serveur p12 ⇒ Convertir en cer

$ openssl pkcs12 -in server-crt.p12 -des -out server-crt.cer

keytool (outil de gestion des clés et des certificats)

Installez keytool

https://jp.globalsign.com/support/faq/331.html

Créer un fichier de keystore

Référence de la commande: https://docs.oracle.com/javase/jp/6/technotes/tools/windows/keytool.html

Il semble que Java ne pourra pas se mettre à jour automatiquement si cacerts change. Sauvegarde requise. http://d.hatena.ne.jp/uunfo/20110813/1313242092

keytool -genkeypair -keysize 2048 -keyalg RSA -sigalg SHA256withRSA -alias testcrt -keystore "C:\Program Files\Java\jreX.X.X_XXX\lib\security\cacerts" -storepass changeit

** Ajouté le 16/10/2017 ** Créez un fichier de clés n'importe où (Lorsque le nom commun est test1, l'unité organisationnelle est test2, l'organisation est test3 et le code de pays à deux caractères est JP)

$ keytool -genkey -dname "cn=test1, ou=test2, o=test3, c=JP" -keystore (nom du fichier de keystore).keystore) -alias (nom qui identifie le certificat / la clé dans le KeyStore)-keypass (certificat / mot de passe clé * 6 caractères ou plus)-storepass (mot de passe du magasin de clés)-keyalg RSA -keysize 2048 -validity 10000

Référence (par génération de paire de clés) https://docs.oracle.com/javase/jp/8/docs/technotes/tools/unix/keytool.html

Ajouter un certificat de serveur au magasin de clés

J'ai pensé que ce serait une bonne idée de laisser le certificat exposé en tant que ressource externe, j'ai donc envisagé d'importer le certificat dans le magasin de clés.

Importer le fichier cer dans le keystore

Lorsque j'essaye d'importer le fichier crt avec la commande suivante, j'obtiens une erreur disant "erreur keytool: java.lang.Exception: L'entrée n'est pas un certificat X.509". Importez avec cer.

$ keytool -import -alias testkey -keystore "C:\Program Files\Java\jreX.X.X_XXX\lib\security\cacerts" -file server-crt.cer

Importer le fichier p12 dans le keystore http://blogger.fastriver.net/2014/10/keytool.html

Si vous ne spécifiez pas d'alias (nom distinctif), il sera importé avec le nom "1" par défaut. Si vous souhaitez ajouter un alias, ajoutez une option telle que "-srcalias 1 -destalias (nom d'alias arbitraire)".

$ keytool -importkeystore -keystore "C:\Program Files\Java\jreX.X.X_XXX\lib\security\cacerts" -srckeystore server-crt.p12 -srcstoretype PKCS12 -srcalias 1 -destalias testcrt -srcstorepass root -deststorepass changeit

Vérifiez le certificat importé

$ keytool -list -v -alias testcrt -keystore "C:\Program Files\Java\jreX.X.X_XXX\lib\security\cacerts" -keypass root -storepass changeit

Supprimer le certificat importé du keystore

$ keytool -delete -alias testcrt -keystore "C:\Program Files\Java\jreX.X.X_XXX\lib\security\cacerts" -keypass root -storepass changeit

Changer le nom de l'alias (lors du passage de 11111111 à 22222222)

$ keytool -changealias -srcalias 11111111 -destalias 22222222 -keystore "C:\Program Files\Java\jreX.X.X_XXX\lib\security\cacerts" -keypass root -storepass changeit

Prolonger la date d'expiration du certificat (lors de la définition après 2000 jours)

$ keytool -selfcert -alias testcrt -validity 2000 -keystore "C:\Program Files\Java\jreX.X.X_XXX\lib\security\cacerts" -keypass root -storepass changeit

Code Java terminé

createSignedXml.java


    public String createSignedXml(String fileName)
            throws Exception {

        //Créer une instance de document
        DocumentBuilder documentBuilder = null;
        documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();

        Document document = documentBuilder.newDocument();

        //Génération DOM du document XML (omis)

        //Création de signature XML
        //chemin du fichier p12
        File certDir = "XXXXXX";
        //Liste des fichiers de certificats sous le répertoire des certificats (en supposant qu'un seul fichier existe)
        File[] certP12List = certDir.listFiles((FileFilter) new SuffixFileFilter(".p12"));
        //Fichier de certificat
        File certP12File = null;
        //Obtenez le chemin du fichier keystore
        String keyStoreFilePath = "/usr/java/jdkX.X.X_XXX/jre/lib/security/testkeystore";
        //Obtenir le fichier de keystore
        File keyStoreFile = new File(keyStoreFilePath);
        //Mot de passe du fichier de clés
        String keyStorePass = "root";
        //Mot de passe du certificat
        String certificatePass = "changeit";

        //Erreur si plusieurs fichiers p12 sont placés
        if (certP12List.length == 1) {
            certP12File = certP12List[0];
        } else {
            throw new IOException();
        }

        try {
            //Obtenez le keystore
            KeyStore keyStore = getKeyStore(keyStoreFile, keyStorePass);

            //Nom distinctif: obtenez un certificat correspondant à XXX à partir du magasin de clés
            X509Certificate x509cert = getCertificate(keyStore, XXX);

            //Drapeau de jugement d'importation de certificat
            boolean importFlg = false;

            //Pour vérifier la date d'expiration
            // 0:Le certificat importé est dans la date d'expiration, 1:Le certificat importé a expiré,
            // 2:Le certificat de ressource externe a expiré, 3:Les deux ont expiré, 4:Erreur d'importation
            int checkResult = 0;

            if (x509cert != null) {
                //Contrôle d'expiration des certificats placés dans des ressources externes et des certificats importés
                checkResult = checkCertificateExpired(x509cert, XXX, keyStoreFile, certP12File, keyStorePass, certificatePass);

                //Le certificat importé a expiré
                if (checkResult == 1) {
                    //Nom distinctif: XXX supprimer le certificat
                    deleteProcessExec(XXX, keyStoreFile, certificatePass, keyStorePass);

                    importFlg = true;
                }
            } else {
                importFlg = true;
            }

            //Si le certificat importé dans le keystore a expiré
            //Réimporter un nouveau certificat
            if (importFlg) {
                //Effectuer l'importation de certificats
                importProcessExec(keyStoreFile, XXX, certP12File, certificatePass, keyStorePass);

                //Réacquérir le keystore
                keyStore = getKeyStore(keyStoreFile, keyStorePass);

                //Nom distinctif: obtenez à nouveau un certificat correspondant à XXX à partir du magasin de clés
                x509cert = getCertificate(keyStore, XXX);

                //Vérification de la date d'expiration
                checkResult = checkCertificateExpired(x509cert, keyStoreFile, certP12File, keyStorePass, certificatePass);
            }

            //Le certificat placé dans la ressource externe et le certificat importé ont expiré
            //Erreur d'importation de certificat de ressource externe
            if (checkResult >= 3) {
                //Nom distinctif: XXX supprimer le certificat
                deleteProcessExec(XXX, keyStoreFile, certificatePass, keyStorePass);

                throw new CertificateException();
            }

            //Obtenez la clé privée
            RSAPrivateKey privateKey = (RSAPrivateKey) keyStore.getKey(XXX, certificatePassArray);

            //Créer un contexte de signature
            DOMSignContext dsc = new DOMSignContext(privateKey, document.getDocumentElement());

            XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");

            //Créer un élément de référence
            Reference ref = fac.newReference
                    ("#XXXXXX", fac.newDigestMethod(DigestMethod.SHA256, null),
                            Collections.singletonList
                                    (fac.newTransform(Transform.ENVELOPED,
                                            (TransformParameterSpec) null)), null, null);

            //Création des informations de signature
            SignedInfo si = fac.newSignedInfo
                    (fac.newCanonicalizationMethod
                            (CanonicalizationMethod.INCLUSIVE_WITH_COMMENTS,
                                    (C14NMethodParameterSpec) null),
                            fac.newSignatureMethod("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", null),
                            Collections.singletonList(ref));

            KeyInfoFactory kif = fac.getKeyInfoFactory();
            X509Data x509Data = kif.newX509Data(Collections.singletonList(x509cert));
            KeyInfo ki = kif.newKeyInfo(Collections.singletonList(x509Data));

            //Signe.
            XMLSignature signature = fac.newXMLSignature(si, ki);
            signature.sign(dsc);

        } catch (XMLSignatureException e) {
            throw new XMLSignatureException("Erreur lors du processus de génération ou de validation de la signature XML", e);
        } catch (MarshalException e) {
            throw new MarshalException(e);
        } catch (InvalidAlgorithmParameterException e) {
            throw new InvalidAlgorithmParameterException(e);
        } catch (NoSuchAlgorithmException e) {
            throw new NoSuchAlgorithmException(e);
        } catch (KeyStoreException e) {
            throw new KeyStoreException(e);
        } catch (CertificateException e) {
            throw new CertificateException(e);
        } catch (UnrecoverableKeyException e) {
            throw new UnrecoverableKeyException();
        }

        return this.write(document);
    }

    /**
     *Obtenez le keystore
     *
     * @param keyStoreFile Fichier Keystore
     * @param keyStorePass Mot de passe Keystore
     * @return keyStore, objet keystore
     */
    private KeyStore getKeyStore(File keyStoreFile, String keyStorePass) {
        KeyStore keyStore = null;

        try (FileInputStream keyStoreStream = new FileInputStream(keyStoreFile)) {
            //Type de fichier de clés:JKS(Pour PKCS12, prenez l'argument"PKCS12"Réparer)
            keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            keyStore.load(keyStoreStream, keyStorePass.toCharArray());
        } catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException e) {
            //Bloc de capture généré automatiquement TODO
            e.printStackTrace();
        }

        return keyStore;
    }

    /**
     *Obtenez un certificat qui correspond à votre nom distinctif dans le fichier de clés
     *
     * @objet keystore param keyStore
     * @param alias Nom distinctif
     * @certificat de retour objet Certificat
     */
    private X509Certificate getCertificate(KeyStore keyStore, String alias){
        X509Certificate certificate = null;
        try {
            certificate = (X509Certificate) keyStore.getCertificate(alias);
        } catch (KeyStoreException e) {
            //Bloc de capture généré automatiquement TODO
            e.printStackTrace();
        }
        return certificate;
    }

    /**
     *Vérification d'expiration du certificat
     *
     * @objet de certificat param x509cert X509
     * @param keyStoreFile Fichier Keystore
     * @param certFile Fichier de certificat
     * @param keyStorePass Mot de passe Keystore
     * @param certificatePass Mot de passe du certificat
     * @param srcAlias Nom distinctif temporaire immédiatement après l'importation
     * @return 0:Le certificat importé est dans la date d'expiration, 1:Le certificat importé a expiré,
     * 2:Le certificat de ressource externe a expiré, 3:Les deux ont expiré, 4:Erreur d'importation de certificat de ressource externe
     */
    private int checkCertificateExpired(X509Certificate x509cert,
            File keyStoreFile, File certFile, String keyStorePass, String certificatePass,
            String srcAlias) {
        //Résultat du traitement
        int result = 0;
        //Indicateur d'expiration du certificat importé
        // true:Expiré, false:Dans la date d'expiration
        boolean importExpiredFlg = false;
        //Indicateur d'expiration pour les certificats placés sur des ressources externes
        boolean extExpiredFlg = false;
        //Obtenez la date d'expiration du certificat importé dans le keystore
        Date importExpiredDate = x509cert.getNotAfter();
        //Date et heure actuelles
        Date now = new Date();

        /**************************Contrôle d'expiration du certificat importé START**************************/

        //Déterminez si le certificat importé a expiré
        if (now.compareTo(importExpiredDate) > 0) {
            //S'il a expiré
            importExpiredFlg = true;
            result = 1;
        } else {
            //Puisqu'il est dans la date d'expiration, aucune autre vérification n'est requise
            return 0;
        }
        /***************************Contrôle d'expiration du certificat importé END***************************/

        /***********************Contrôle d'expiration des certificats placés sur des ressources externes START**********************/

        try {
            //Nom distinctif temporaire
            String destAlias = System.currentTimeMillis();

            //Exécuter la commande d'importation
            importProcessExec(keyStoreFile, destAlias, certFile, certificatePass, keyStorePass);

            //Obtenez le keystore
            KeyStore tmpKeyStore = getKeyStore(keyStoreFile, keyStorePass);
            //Nom distinctif: obtenez un certificat qui correspond à destAlias à partir du fichier de clés
            X509Certificate tmpCert = getCertificate(tmpKeyStore, destAlias);

            //Obtenez la date d'expiration du certificat importé
            Date extExpiredDate = null;
            if (tmpCert != null) {
                extExpiredDate = tmpCert.getNotAfter();
            } else {
                //Erreur d'importation
                return 4;
            }

            //Comparez l'heure actuelle avec la date d'expiration du certificat de la ressource externe
            if (now.compareTo(extExpiredDate) > 0) {
                //S'il a expiré
                extExpiredFlg = true;
                result = 2;
            }

            //Exécuter la commande pour supprimer le certificat importé temporairement
            deleteProcessExec(destAlias, keyStoreFile, certificatePass, keyStorePass);

        } catch(InterruptedException e) {
            //Bloc de capture généré automatiquement TODO
            e.printStackTrace();
        }
        /**********************Contrôle d'expiration END pour les certificats placés sur des ressources externes*********************/


        //Certificats importés et certificats placés sur des ressources externes
        //Si les deux ont expiré, le résultat:3
        if (importExpiredFlg && extExpiredFlg) {
            result = 3;
        }

        return result;

    }

    /**
     *Exécutez la commande de suppression de certificat.
     *
     * @param alias Nom distinctif
     * @param keyStoreFile Fichier Keystore
     * @param certificatePass Mot de passe du certificat
     * @param keyStorePass Mot de passe Keystore
     * @return true:Réussite, false:Terminaison anormale
     * @throws InterruptedException
     */
    private boolean deleteProcessExec(String alias, File keyStoreFile, String certificatePass,
            String keyStorePass)
            throws InterruptedException {
        //Obtenez la commande pour supprimer le certificat importé dans le keystore
        List<String> command = getDeleteCommand(alias, keyStoreFile, certificatePass, keyStorePass);
        //Supprimer l'exécution de la commande
        return processExec(command);
    }

    /**
     *Obtenez la commande de suppression de certificat.
     *
     * @param alias Nom distinctif
     * @param keyStoreFile Fichier Keystore
     * @param certificatePass Mot de passe du certificat
     * @param keyStorePass Mot de passe Keystore
     * @return commande de suppression de resultList
     */
    private List<String> getDeleteCommand(String alias, File keyStoreFile, String certificatePass,
            String keyStorePass) {
        //Commande pour supprimer le certificat importé dans le keystore
        String command = "keytool -delete -alias %alias% -keystore %keyStoreFilePath% -keypass %certificatePass% -storepass %keyStorePass%";

        //Commande Split en tableau de chaînes
        String[] commandList = command.split(" ");

        List<String> resultList = new ArrayList<String>();
        for (String cmd : commandList) {
            switch (cmd) {
            case "%alias%":
                cmd = cmd.replace("%alias%", alias);
                break;
            case "%keyStoreFilePath%":
                cmd = cmd.replace("%keyStoreFilePath%", keyStoreFile.getPath());
                break;
            case "%certificatePass%":
                cmd = cmd.replace("%certificatePass%", certificatePass);
                break;
            case "%keyStorePass%":
                cmd = cmd.replace("%keyStorePass%", keyStorePass);
                break;
            }
            resultList.add(cmd);
        }

        return resultList;
    }

    /**
     *Exécutez la commande d'importation de certificat.
     *
     * @param fichier de certificat certFilePath
     * @param destAlias Nom distinctif
     * @param keyStoreFilePath Fichier Keystore
     * @param certificatePass Mot de passe du certificat
     * @param keyStorePass Mot de passe Keystore
     * @return true:Réussite, false:Terminaison anormale
     * @throws InterruptedException
     */
    private boolean importProcessExec(File keyStoreFile, String destAlias, File certFile,
            String certificatePass,
            String keyStorePass) throws InterruptedException {
        //Commande pour importer le certificat
        List<String> command = getImportCommand(keyStoreFile, destAlias, certFile, certificatePass,
                keyStorePass);
        //Exécuter la commande d'importation
        return processExec(command);
    }

    /**
     *Obtenez la commande d'importation de certificat.
     *
     * @param fichier de certificat certFilePath
     * @param destAlias Nom distinctif
     * @param keyStoreFilePath Fichier Keystore
     * @param certificatePass Mot de passe du certificat
     * @param keyStorePass Mot de passe Keystore
     * @return commande d'importation resultList
     */
    private List<String> getImportCommand(File keyStoreFile, String destAlias, File certFile,
            String certificatePass, String keyStorePass) {
        //Commande pour importer le certificat
        String command = "keytool -importkeystore -keystore %keyStoreFilePath% -srckeystore %certFilePath% -srcstoretype PKCS12 -srcalias 1 -destalias %destalias% -srcstorepass %certificatePass% -deststorepass %keyStorePass%";

        //Commande Split en tableau de chaînes
        String[] commandList = command.split(" ");

        List<String> resultList = new ArrayList<String>();

        for (String cmd : commandList) {
            switch (cmd) {
            case "%keyStoreFilePath%":
                cmd = cmd.replace("%keyStoreFilePath%", keyStoreFile.getPath());
                break;
            case "%certFilePath%":
                cmd = cmd.replace("%certFilePath%", certFile.getPath());
                break;
            case "%destalias%":
                cmd = cmd.replace("%destalias%", destAlias);
                break;
            case "%certificatePass%":
                cmd = cmd.replace("%certificatePass%", certificatePass);
                break;
            case "%keyStorePass%":
                cmd = cmd.replace("%keyStorePass%", keyStorePass);
                break;
            }
            resultList.add(cmd);
        }

        return resultList;
    }

    /**
     *Exécutez un processus externe.
     *
     * @commande param Contenu de la commande
     * @return true:Réussite, false:Terminaison anormale
     */
    private boolean processExec(List<String> command) {
        //Résultat du traitement
        boolean result = false;

        try {
            ProcessBuilder processBuilder = new ProcessBuilder(command);
            Process Process = processBuilder.start();

            //Attendez que le processus se termine normalement
            if (Process.waitFor() == 0) {
                result = true;
                log.info("Process Success: " + command.toString());
            } else {
                log.warn("Process Failed: " + command.toString());
            }

            //Sortie standard
            String strInput;
            BufferedReader ipbr = new BufferedReader(new InputStreamReader(Process.getInputStream()));
            while((strInput = ipbr.readLine()) != null) {
                log.info(strInput);
            }
            ipbr.close();

            //Sortie d'erreur
            String strErr;
            BufferedReader erbr = new BufferedReader(new InputStreamReader(Process.getErrorStream()));
            while((strErr = erbr.readLine()) != null) {
                log.info(strErr);
            }
            erbr.close();

            //InputStream en arrière-plan après l'utilisation de ProcessBuilder, OutputStream,ErrorStream est ouvert.
            //Fermez tous les flux pour éviter de manquer de ressources.
            Process.getInputStream().close();
            Process.getOutputStream().close();
            Process.getErrorStream().close();
        } catch (InterruptedException | IOException e) {
            //Bloc de capture généré automatiquement TODO
            e.printStackTrace();
        }

        return result;
    }

Recommended Posts

Certificat électronique ceci et cela
[Rails] strftime ceci et cela
Encodeur Base64 ceci et cela
Ceci et cela de JDK
Ceci et cela à propos de Base64 (Java)
Ceci et cela du contrôle exclusif
Ceci et cela de Swift Corner Radius
Ceci et celui de la dérivation conditionnelle du développement des rails
Ceci et cela pour éditer ini en Java. : inieditor-java
J'ai essayé de vérifier ceci et celui de Spring @ Transactional
Opération de chaîne de caractères ceci et cela-version Java-
Ceci et cela de la mise en œuvre du jugement en temps réel des dates en Java