web-dev-qa-db-fra.com

Quelle est la meilleure pratique pour stocker la clé privée, le sel et le vecteur d'initialisation dans la base de données?

Je travaille sur Java application pour créer une signature numérique pour signer un document. J'ai déjà créé une clé privée et une clé publique en utilisant (cryptographie à courbe elliptique) ECC, et maintenant je veux stocker les deux clés dans la base de données mysql.

Je n'ai aucun problème avec la clé publique, mais mon souci est de stocker en toute sécurité la clé privée.

J'utilise AES 128 bits pour crypter la clé privée et le mot de passe à 6 chiffres de l'utilisateur à stocker dans la base de données. Pour le crypter, je dois également générer du sel et initialiser le vecteur.

Mais maintenant, pour le déchiffrer, j'ai également besoin de connaître le même sel et le même vecteur d'initialisation (iv) que j'utilise pour déchiffrer la clé privée chiffrée.

Question 1:

Est-il sûr de stocker le sel et le vecteur dans la même table de base de données avec une clé privée? Actuellement, j'encode les clés publiques et privées, salt et iv et les enregistre sous forme de chaîne (type de données VARCHAR) dans la base de données.

Question 2:

Vous trouverez ci-dessous le workflow actuel que je conçois. Est-ce la meilleure pratique? Je ne veux pas faire trop de processus qui affectera l'utilisation du processeur.

Création de clé

  • Créer une clé privée à l'aide d'ECC
  • Encode la clé privée (octets en chaîne)
  • Crypter la clé privée à l'aide d'AES
  • Encode la clé privée, salt, iv (octets en chaîne)
  • Stocker dans la base de données en tant que VARHCAR

Document de signature

  • Récupérer la clé privée de la base de données
  • Décoder la clé privée, sel, iv
  • Déchiffrer la clé privée
  • Décoder la clé privée
  • Convertir la clé décodée en clé privée réelle pour la signature

Extrait de code pour générer la clé et le chiffrement:

        //Generate salt
        Random r = new SecureRandom();
        byte[] salt = new byte[8];
        r.nextBytes(salt);
        //System.out.println("salt: "+salt);

        //initialize vector
        byte[] vector = new byte[128/8];
        r.nextBytes(vector);
        IvParameterSpec ivspec = new IvParameterSpec(vector);
        //System.out.println("iv: "+iv);

        //initialize variables
        String MsgToEncrypt = encodedECCprivateKeyBytes;
        String userPin = ParamUtil.getString(actionRequest, "userPin");
        Cipher ecipher;

        //Generating AES key
        SecretKeyFactory factory =  SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
        KeySpec mykeySpec = new PBEKeySpec(userPin.toCharArray(), salt, 10000, 128);
        SecretKey tmp = factory.generateSecret(mykeySpec);
        SecretKeySpec mySecretkey = new SecretKeySpec(tmp.getEncoded(), "AES");

        //==> Create and initiate encryption
        System.out.println("Initiate encryption alogrithm...");
        ecipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        //System.out.println("Algorithm to encrypt private key: " + ecipher);
        ecipher.init(Cipher.ENCRYPT_MODE, mySecretkey, ivspec);
        //System.out.println("SecKey: "+mySecretkey);
7

Je vais répondre à votre question en deux parties puisque vous l'avez posée en deux parties:

Question 1: Est-il sûr de stocker le sel et le vecteur dans la même table de base de données avec la clé privée? Actuellement, j'encode les clés publiques et privées, salt et iv et les enregistre sous forme de chaîne (type de données VARCHAR) dans la base de données.

Réponse courte: Oui, c'est sécurisé.

Explication: Il est généralement admis que la conservation de salt en texte brut à côté du mot de passe haché est sécurisée. Ceci est basé sur la logique selon laquelle si un attaquant a le sel et le hachage, il doit toujours utiliser une attaque par force brute pour tenter de deviner le mot de passe utilisé pour créer le hachage. Garder le sel secret aussi améliorerait la sécurité mais tant que le mot de passe est raisonnablement fort, pas nécessaire. Pour l'IV, il est beaucoup plus compliqué et à mon avis hors de portée d'entrer ici (et hors de ma zone de confort pour l'expliquer), mais il est considéré comme sûr pour l'IV d'être stocké en texte brut à côté du chiffre- texte.

Question 2: Ci-dessous est le flux de travail actuel que je conçois. Est-ce la meilleure pratique? Je ne veux pas faire trop de processus qui affectera l'utilisation du processeur.

Le flux de travail me semble bon et est à peu près le même que j'aurais fait, avec quelques détails que je pense que vous pouvez améliorer car vous demandez les meilleures pratiques:

  1. Tout d'abord, votre sel est un peu trop court. Le problème avec cela est qu'avec un sel de 8 octets, même lorsqu'il est généré à l'aide d'un générateur crypto-aléatoire (comme vous, ce qui est bien), il y a un risque de collision où deux ou plusieurs utilisateurs différents se voient attribuer la même valeur de sel. Pour atténuer cela, la recommandation que je suis est une longueur de sel de 256 bits ou 32 octets.

  2. Deuxième conseil et je ne suis pas sûr basé sur votre code si vous le connaissez déjà, mais assurez-vous de ne jamais réutiliser le même IV avec la même clé AES deux fois. En raison d'une cryptanalyse très sophistiquée, cela peut créer des vulnérabilités dans le cryptage, ce qui le rend cassable. Étant donné que la clé est générée à partir d'un mot de passe utilisateur qui, je suppose, est rarement modifié, assurez-vous de faire pivoter l'IV chaque fois que vous rechiffrez la clé privée.

  3. Il semble que vous ne fassiez actuellement que 10 000 cycles de hachage. Bien que ce ne soit pas horrible, la règle d'or que j'ai toujours suivie est de 2 ^ (an 2000) itérations. Depuis 2018, 250 000 itérations de hachage ou près de cette valeur que vous pouvez obtenir avant d'atteindre des problèmes de performances graves est la meilleure pratique.

Sinon, je pense que tout semble bon, vous avez fait un bon choix dans les algorithmes de hachage et de clé publique-privée et avez été sage de demander de l'aide pour vous assurer de ne rien oublier.

J'espère que cela aide!

8
dFrancisco

Oui. Il est sûr de stocker le sel et l'IV à côté de l'entrée cryptée.

Pour comprendre pourquoi, vous devez creuser exactement ce que le sel et l'IV sont destinés à faire.

Le sel est conçu comme un moyen de faire en sorte que si ne entrée est fissurée, elle ne se répercutera pas sur d'autres entrées. Si vous aviez un tableau de mots de passe cryptés qui n'étaient pas hachés, dès que quelqu'un a craqué un enregistrement, il aurait également cracké simultanément tous les enregistrements qui partageaient le même mot de passe décrypté. Le Salt n'est pas censé rendre le forçage brutal plus difficile; il vise uniquement à garantir que chaque entrée est isolée au niveau du chiffrement de toutes les autres entrées. Donc, peu importe si l'attaquant connaît l'entrée de sel pour un enregistrement donné - tant que vous utilisez un sel différent pour chaque entrée, le sel fait son travail.

De même, l'IV est censé arrêter les attaques connues de Plaintext. Son but est d'empêcher quelqu'un d'exploiter "Ces entrées X partagent toutes un contenu similaire dans les octets X-Y" et d'utiliser la cryptoanalyse pour déduire des aspects de la clé. L'IV brouille essentiellement les données avant qu'elles ne soient cryptées. Donc, connaître l'IV n'aide pas non plus l'attaquant.

Alors allez-y et stockez l'IV et le sel à côté de la valeur cryptée.

4
Kevin