AES CTR 256 Cryptage de Mode de fonctionnement sur OpenSSL
Im nouveau à OpenSSL, quelqu'un Peut-il me donner une idée de comment initialiser AES CTR mode à partir d'un fichier C. Je sais que c'est les méthodes de signature, mais je vais avoir des problèmes avec les paramètres, il n'y a pas beaucoup de documentation ni un exemple clair comment faire un simple chiffrement. Je vous serais reconnaissant si quelqu'un pourrait illustrer un appel à cette méthode. Merci à l'avance!
void AES_ctr128_encrypt(const unsigned char *in, unsigned char *out,
const unsigned long length, const AES_KEY *key,
unsigned char ivec[AES_BLOCK_SIZE],
unsigned char ecount_buf[AES_BLOCK_SIZE],
unsigned int *num);
Hi Fac, j'ai vraiment apprécié votre réponse rapide, il a été vraiment utile, et defenetly le meilleur exemple que j'ai trouvé sur le web. Je suis en train d'essayer d'ouvrir un fichier avec indéterminée longueur, de chiffrer et d'écrire un autre fichier avec le texte chiffré généré, puis ouvrez le fichier chiffré et récupérer le texte brut. J'ai besoin d'utiliser un fichier d'une quantité considérable de MO en cause je voudrais pour indice de référence les performances de l'UC. Cependant je suis encore avoir un problème lors du déchiffrement. D'une certaine manière lors du déchiffrement d'un considérable des fichiers txt (1504KB)il l'habitude de décrypter complet, et je reçois la moitié en clair et l'autre moitié reste encore chiffré. Je pense que cela pourrait être lié à la taille de la iv ou de la façon dont je suis l'appel de la contre. Voici ce que j'ai à ce jour:
#include <openssl/aes.h>
#include <stdio.h>
#include <string.h>
struct ctr_state {
unsigned char ivec[16];
unsigned int num;
unsigned char ecount[16];
};
FILE *fp;
FILE *rp;
FILE *op;
size_t count;
char * buffer;
AES_KEY key;
int bytes_read, bytes_written;
unsigned char indata[AES_BLOCK_SIZE];
unsigned char outdata[AES_BLOCK_SIZE];
unsigned char ckey[] = "thiskeyisverybad"; //It is 128bits though..
unsigned char iv[8] = {0};//This should be generated by RAND_Bytes I will take into consideration your previous post
struct ctr_state state;
int init_ctr(struct ctr_state *state, const unsigned char iv[8]){
state->num = 0;
memset(state->ecount, 0, 16);
memset(state->ivec + 8, 0, 8);
memcpy(state->ivec, iv, 8);
}
void encrypt(){
//Opening files where text plain text is read and ciphertext stored
fp=fopen("input.txt","a+b");
op=fopen("output.txt","w");
if (fp==NULL) {fputs ("File error",stderr); exit (1);}
if (op==NULL) {fputs ("File error",stderr); exit (1);}
//Initializing the encryption KEY
AES_set_encrypt_key(ckey, 128, &key);
//Encrypting Blocks of 16 bytes and writing the output.txt with ciphertext
while (1) {
init_ctr(&state, iv); //Counter call
bytes_read = fread(indata, 1, AES_BLOCK_SIZE, fp);
AES_ctr128_encrypt(indata, outdata, bytes_read, &key, state.ivec, state.ecount, &state.num);
bytes_written = fwrite(outdata, 1, bytes_read, op);
if (bytes_read < AES_BLOCK_SIZE)
break;
}
fclose (fp);
fclose (op);
free (buffer);
}
void decrypt(){
//Opening files where text cipher text is read and the plaintext recovered
rp=fopen("recovered.txt","w");
op=fopen("output.txt","a+b");
if (rp==NULL) {fputs ("File error",stderr); exit (1);}
if (op==NULL) {fputs ("File error",stderr); exit (1);}
//Initializing the encryption KEY
AES_set_encrypt_key(ckey, 128, &key);
//Encrypting Blocks of 16 bytes and writing the output.txt with ciphertext
while (1) {
init_ctr(&state, iv);//Counter call
bytes_read = fread(indata, 1, AES_BLOCK_SIZE, op);
AES_ctr128_encrypt(indata, outdata, bytes_read, &key, state.ivec, state.ecount, &state.num);
bytes_written = fwrite(outdata, 1, bytes_read, rp);
if (bytes_read < AES_BLOCK_SIZE)
break;
}
fclose (rp);
fclose (op);
free (buffer);
}
int main(int argc, char *argv[]){
encrypt();
//decrypt();
system("PAUSE");
return 0;
}
Chaque chiffrer et déchiffrer les fonction sont appelés dans les différentes courses donc tout est initialisé avec toujours les mêmes valeurs. Merci encore pour les conseils que vous pouvez me fournir à l'avance & Cordialement!!!
- Votre problème est que vous êtes reinitialising le compteur après chaque bloc. Ce qui est faux, - déplacer le
init_ctr()
appel à l'extérieur de lawhile()
boucles dans le chiffrement et le déchiffrement.indata
etoutdata
aussi n'avez pas à être deAES_BLOCK_SIZE
longueur - ils peuvent être beaucoup plus grandes. - Vous ne devez pas utiliser
AES_encrypt
et amis. C'est un logiciel de mise en œuvre, de sorte que vous ne serez pas profiter de matériel de soutien, comme l'AES-NI. Vous devriez être en utilisantEVP_*
fonctions. Voir EVP Symétrique de Chiffrement et de Déchiffrement sur la OpenSSL wiki. En fait, vous devriez probablement être authentifié à l'aide de chiffrement, car il fournit à la fois la confidentialité et l'authenticité. Voir EVP Authentifié de Chiffrement et de Déchiffrement sur la OpenSSL wiki. - Si vous utilisez le
EVP_*
fonctions, puis les algorithmes d'intérêt sontEVP_aes_128_ctr
,EVP_aes_192_ctr
etEVP_aes_256_ctr
.
Vous devez vous connecter pour publier un commentaire.
Habituellement, vous serez l'intention d'appeler
AES_ctr128_encrypt()
à plusieurs reprises pour envoyer plusieurs messages avec la même clé et IV, et une incrémentation du compteur. Cela signifie que vous devez garder une trace de la 'ivec', 'num' et 'ecount valeurs entre les appels - afin de créer unstruct
pour la tenue de ces, et une phase d'initialisation de la fonction:Maintenant, lorsque vous commencez à communiquer avec la destination, vous aurez besoin de générer un IV à utiliser et permet d'initialiser le compteur:
Vous devrez ensuite envoyer les 8 octets IV de la destination. Vous aurez également besoin de l'initialiser un
AES_KEY
à partir de votre clé brute octets:Vous pouvez maintenant démarrer le chiffrement des données et de l'envoyer à la destination, avec les appels répétés à la
AES_ctr128_encrypt()
comme ceci:(
msg_in
est un pointeur sur un buffer contenant le message en clair,msg_out
est un pointeur vers une mémoire tampon où le message chiffré devrait aller, etmsg_len
est la longueur du message).De déchiffrement est exactement le même, sauf que vous ne générez pas les IV avec
RAND_bytes()
- au lieu de cela, vous prenez la valeur donnée par l'autre côté.Important:
Ne pas appel
init_ctr()
plus d'une fois pendant le processus de cryptage. Le compteur et IV doivent être initialisées une seule fois avant le début de chiffrement.En aucun cas être tentés d'obtenir le IV n'importe où d'autre que de
RAND_bytes()
sur le chiffrement côté. Ne pas définie à une valeur fixe; - ne pas utiliser une fonction de hachage; n'utilisez pas le nom du destinataire; ne pas le lire à partir du disque. Générer avecRAND_bytes()
et de l'envoyer à la destination. Chaque fois que vous démarrez avec un zéro de compteur, vous doit commencer avec un complètement nouveau, IV que vous n'avez jamais utilisé auparavant.Si il est possible que vous enverrez 2**64 octets sans changer le IV et/ou de la clé, vous aurez besoin de tester pour le compteur de débordement.
N'omettez pas de vérification des erreurs. Si la fonction échoue et que vous ignorez, c'est tout à fait possible (voire probable) que votre système semble fonctionner normalement, mais sera effectivement d'exploitation complètement de manière non sécurisée.
num
etecount
opaque état interne de l'OpenSSL CTR mise en œuvre. Dans la plupart des cas, il ne devrait pas être nécessaire de modifier directement entre eux.Il ressemble au problème de base avec votre programme de test est que la mode des valeurs de la
fopen
appels n'est pas correct. Je pense que vous avez besoin de changer votre fopen appels à chiffrer à ce:Et celles de déchiffrer à:
Une autre chose à noter est que
ckey
devrait probablement être déclarés en tant que de 32 octets (256 bits) de mémoire tampon. Il est vrai que le cryptage 128 bits utilise uniquement les 16 octets de données à partir de la clé. Mais la OpenSSL fonctionAES_set_encrypt_key
(au moins dans la version que j'utilise) lit de 32 octets de la mémoire tampon. Il utilise uniquement le nombre d'octets approprié, mais la lecture ne se produisent. Cela signifie que si le tampon est seulement de 16 octets, et arrive à la fin à la fin d'une page qui est adjacent à un non lisibles à la page dans la mémoire, il en résulterait une violation d'accès.Oh et je viens de remarquer qu'il y a un parasite appel à
free
là. Lefree(buffer);
appel n'est pas valide, car tampon n'a jamais été alloué. Je me rends compte que votre code est juste un test simple, mais ... eh bien, nous sommes des programmeurs et ne peut pas nous aider.