Re: [Un peu HS] Utilisation de l'API OpenSSL
didier gaumet a écrit : > Le 04/07/2024 à 20:44, BERTRAND Joël a écrit : >> didier gaumet a écrit : > [...] >>> https://stackoverflow.com/questions/71763461/purpose-of-evp-encryptfinal-ex-function-in-openssl >>> > [...] > >> Ce que je ne saisis pas, c'est pour quoi lorsqu'on >> a déjà un multiple d'une longueur de bloc, la fonction en rajoute un. Et >> pourquoi elle plante lamentablement en cas de déchiffrement. > [...] > > comme dit précédemment, tout ça me passe un peu au-dessus de ce qui me > sert malaisément de cerveau mais le lien ci-dessus a quelques > explications intéressantes fournies par un type quia l'air de comprendre > à peu près de quoi il parle, et ça renvoie vers l'explication Wikipedia > du mode d'opération de chiffrement, section "remplissage": > https://fr.wikipedia.org/wiki/Mode_d%27op%C3%A9ration_(cryptographie)#Remplissage > > (comme on est sur une liste en français, je pointe vers un lien en > français, mais le texte original en anglais est peut-être plus à jour ou > plus complet) > > donc j'ai pas creusé mais une explication du comportement que tu > observes (des blocs de 16 bits dont seuls 15 utilisés passent mais pas > des blocs de 16 bits comportant 16 bits utiles) pourrait résider dans le > mode utilisé, je cite: > "[...] Un peu plus complexe est la méthode DES originale, qui consiste > à ajouter un seul bit, suivi de suffisamment de bits zéro pour remplir > le bloc ; si le message se termine sur une limite de bloc, un bloc de > remplissage entier sera ajouté. [...]" Rien à voir, je suis en ECB. Donc chaque bloc est chiffré séparément. Le problème est "pourquoi openssl bourre-t-il un nouveau bloc de 16 octets alors qu'il n'a pas besoin de le faire ?" Le chiffrement est le suivant : 16 octets -> AES256 -> 16 octets (et non 32). JB signature.asc Description: OpenPGP digital signature
Re: [Un peu HS] Utilisation de l'API OpenSSL
Le 04/07/2024 à 20:44, BERTRAND Joël a écrit : didier gaumet a écrit : [...] https://stackoverflow.com/questions/71763461/purpose-of-evp-encryptfinal-ex-function-in-openssl [...] Ce que je ne saisis pas, c'est pour quoi lorsqu'on a déjà un multiple d'une longueur de bloc, la fonction en rajoute un. Et pourquoi elle plante lamentablement en cas de déchiffrement. [...] comme dit précédemment, tout ça me passe un peu au-dessus de ce qui me sert malaisément de cerveau mais le lien ci-dessus a quelques explications intéressantes fournies par un type quia l'air de comprendre à peu près de quoi il parle, et ça renvoie vers l'explication Wikipedia du mode d'opération de chiffrement, section "remplissage": https://fr.wikipedia.org/wiki/Mode_d%27op%C3%A9ration_(cryptographie)#Remplissage (comme on est sur une liste en français, je pointe vers un lien en français, mais le texte original en anglais est peut-être plus à jour ou plus complet) donc j'ai pas creusé mais une explication du comportement que tu observes (des blocs de 16 bits dont seuls 15 utilisés passent mais pas des blocs de 16 bits comportant 16 bits utiles) pourrait résider dans le mode utilisé, je cite: "[...] Un peu plus complexe est la méthode DES originale, qui consiste à ajouter un seul bit, suivi de suffisamment de bits zéro pour remplir le bloc ; si le message se termine sur une limite de bloc, un bloc de remplissage entier sera ajouté. [...]" Enfin, je dis ça, je dis rien, c'est juste une hypothèse et c'est pas moi qui me coltine le problème ;-) plus sérieusement: bon courage :-)
Re: [Un peu HS] Utilisation de l'API OpenSSL
didier gaumet a écrit : > préambule lamentable: j'ai lu ta bafouille en diagonale, je n'ai pas le > niveau, j'ai pas envie de creuser, etc... donc ma réponse ne va > peut-être pas être très pertinente, désolé ;-) > > En très gros de la part d'un inculte du sujet, même si la fonction > openssl semble légèrement différente sur cette page, je me demande si le > mécanisme sur lequel tu butes n'est pas le même (du padding qui > nécessite la décomposition en sous-variables dont la dernière doit être > traitée par une fonction de type "final"): > https://stackoverflow.com/questions/71763461/purpose-of-evp-encryptfinal-ex-function-in-openssl > > > j'ai peut-être rien compris, hein, c'est hors de mes maigres compétences > et je n'ai de plus pas envie de vriller les pauvres neurones qui me > restent à chercher à comprendre ;-) Ça tourne effectivement autour de cela. Je connais la différence entre les deux fonctions. Ce qui me dérange, c'est que dans tous les exemples que j'ai pu trouver EVP_CipherFinal_ex() est toujours appelée sur le dernier bloc (pour bourrer les octets manquant pour avoir un multiple de la longueur de bloc). Ce que je ne saisis pas, c'est pour quoi lorsqu'on a déjà un multiple d'une longueur de bloc, la fonction en rajoute un. Et pourquoi elle plante lamentablement en cas de déchiffrement. Je pense (naïvement sans doute) que si aucun test n'est fait dans les exemples sur la longueur des données à chiffrer, cette fonction doit être appelée dans tous les cas. Bien cordialement, JB signature.asc Description: OpenPGP digital signature
Re: [Un peu HS] Utilisation de l'API OpenSSL
préambule lamentable: j'ai lu ta bafouille en diagonale, je n'ai pas le niveau, j'ai pas envie de creuser, etc... donc ma réponse ne va peut-être pas être très pertinente, désolé ;-) En très gros de la part d'un inculte du sujet, même si la fonction openssl semble légèrement différente sur cette page, je me demande si le mécanisme sur lequel tu butes n'est pas le même (du padding qui nécessite la décomposition en sous-variables dont la dernière doit être traitée par une fonction de type "final"): https://stackoverflow.com/questions/71763461/purpose-of-evp-encryptfinal-ex-function-in-openssl j'ai peut-être rien compris, hein, c'est hors de mes maigres compétences et je n'ai de plus pas envie de vriller les pauvres neurones qui me restent à chercher à comprendre ;-)
[Un peu HS] Utilisation de l'API OpenSSL
Bonjour à tous, Désolé de venir avec un problème pas tout à fait Debian. J'essaye de m'inscrire sur les listes de diffusion OpenSSL depuis plusieurs jours sans aucun retour. Je pense que des lecteurs ont déjà été confrontés au problème. J'utilise OpenSSL (3.3.1) pour chiffrer des messages et les déchiffrer. J'observe un comportement que je ne comprends pas. Je n'utilise qu'un chiffrement de type AES256-ECB (donc le chiffrement d'un bloc ne dépend que du bloc en question. Je sais, ce n'est pas bien, mais le périphérique en face est un microcontrôleur qui cause en 4G et qui possède très peu de mémoire). Lorsque mon périphérique parle à mon serveur Debian, mon programme plante méchamment lors de l'appel à la fonction EVP_CipherFinal_ex(). Que fais-je ? Je crée un contexte, je l'initialise avec la clef et tout ce qui va bien puis je chiffre : if ((contexte = EVP_CIPHER_CTX_new()) == NULL) { return(NULL); } EVP_CIPHER_CTX_reset(contexte); longueur_bloc_de_chiffrement = EVP_CIPHER_block_size(type_chiffrement); if (EVP_CipherInit_ex(contexte, type_chiffrement, NULL, clef, vecteur_initialisation, (encodage == d_vrai) ? 1 : 0) != 1) { EVP_CIPHER_CTX_free(contexte); return(NULL); } nombre_blocs = longueur_message / longueur_bloc_de_chiffrement; if ((longueur_message % longueur_bloc_de_chiffrement) != 0) { nombre_blocs++; } (*longueur_message_chiffre) = nombre_blocs * longueur_bloc_de_chiffrement; printf("longueur_message_chiffre = %lld\n", (*longueur_message_chiffre)); // On prévoit une zone de garde pour EVP_CipherFinal_ex() en // espérant // qu'il ne faille pas plus qu'une longueur de bloc de chiffrement. // Méchant hack en raison d'un comportement étrange de // EVP_CipherFinal_ex(). if ((message_chiffre = malloc(((size_t) ((*longueur_message_chiffre) + longueur_bloc_de_chiffrement)) * sizeof(unsigned char))) == NULL) { EVP_CIPHER_CTX_free(contexte); return(NULL); } printf("longueur_message = %d\n", (int) longueur_message); if (EVP_CipherUpdate(contexte, message_chiffre, &longueur_message_1, message, (int) longueur_message) != 1) { free(message_chiffre); EVP_CIPHER_CTX_free(contexte); return(NULL); } printf("longueur_message_1 = %d\n", longueur_message_1); if (EVP_CipherFinal_ex(contexte, message_chiffre + longueur_message_1, &longueur_message_2) != 1) { free(message_chiffre); EVP_CIPHER_CTX_free(contexte); return(NULL); } printf("longueur_message_2 = %d\n", longueur_message_2); (*longueur_message_chiffre) = longueur_message_1 + longueur_message_2; // Mise à jour du vecteur d'initialisation EVP_CIPHER_CTX_get_updated_iv(contexte, vecteur_initialisation, (size_t) EVP_CIPHER_iv_length(type_chiffrement)); EVP_CIPHER_CTX_free(contexte); Cette routine est appelée pour chiffrer et pour déchiffrer. Je ne mets pas tout le code, ça n'a pas beaucoup d'intérêt. Maintenant, mon problème. Le code AES256 utilise des blocs de 16 octets. Si je chiffre un message de 15 octets, j'obtiens un message chiffré de 16 octets. Normal. longueur_message_chiffre = 16 longueur_message = 15 longueur_message_1 = 0 longueur_message_2 = 16 Ainsi, EVP_CipherUpdate() ne fait rien (aucun bloc entier) et le chiffrement est effectué par EVP_CipherFinal_ex(). Si maintenant je cherche à chiffrer un message de 16 octets, voici ce qui sort : longueur_message_chiffre = 16 longueur_message = 16 longueur_message_1 = 16 longueur_message_2 = 16 => longueur_message_chiffre donne la longueur nécessaire au chiffrement du message. La longueur effectivement renvoyée est longueur_message_1+longueur_message_2 soit ici 32 ! Si je comprends bien, EVP_CipherUpdate() chiffre un bloc de 16 octets. Mais pourquoi EVP_CipherFinal_ex() rajoute-t-il un autre bloc de 16 octets ? J'obtiens un message de 32 octets alors que seuls les 16 premiers sont signifiants. Dans mon cas, j'obtiens : "?r\xF1\xF0-\x89\x83]\xD3\xEE\xF0bj\xE2\xB7\x9E\xE34\xF2\xD2f \xF6w\x02\x14\x0DbS\xD5\x01\x1A" alors que seul "?r\xF1\xF0-\x89\x83]\xD3\xEE\xF0bj\xE2\xB7\x9E" contient le message chiffré (le formalisme est le suivant : les caractères affichables sont directement affichés, les autres sont \x + octet en hexadécimal). Le problème est aussi que je suis capable de déchiffrer le message complet "?r\xF1\xF0-\x89\x83]\xD3\xEE\xF0bj\xE2\xB7\x9E\xE34\xF2\xD2f \xF6w\x02\x14\x0DbS\xD5\x01\x1A" en une chaîne de 16 octets (qui est bien le message envoyé). En revanche, si je tente le déchiffrement des seuls 16 premiers octets, EVP_CipherFinal_ex() renvoie une erreur. Je ne comprends pas mon erreur. Quelqu'un a-t-il déjà été confronté à ce p