2009-11-01 6 views
0

Merci à PBOS aide et son programme (publié here, pour XOR un grand fichier), je fis quelques tests et je vois que j'ai un autre problème: après avoir changé le masque par un autre de 128 bits , il n'y a pas de type par défaut aussi grand que nécessaire.erreur de type 128 bits

Je pense qu'une solution peut être d'inclure une bibliothèque pour augmenter les types entiers disponibles ... mais que je préfère interpréter chaque valeur 128 bits tels que des chaînes. Est-ce possible sans perdre de performance?

Voici le programme en cours (avec le bug « constante entière est trop grand pour son type »):

#include <stdio.h> 
#include <stdlib.h> 

#define BLOCKSIZE 128 
#define MASK 0xA37c54f173f02889a64be02f2bc44112 /* a 128 bits constant */ 

void 
usage(const char *cmd) 
{ 
    fprintf(stderr, "Usage: %s <in-file> [<out-file>]\n", cmd); 
    exit (EXIT_FAILURE); 
} 

int 
main(int argc, char *argv[]) 
{ 
    if (argc < 3) usage(argv[0]); 

    FILE *in = fopen(argv[1], "rb"); 

    if (in == NULL) 
    { 
    printf("Cannot open: %s", argv[2]); 
    return EXIT_FAILURE; 
    } 

    FILE *out = fopen(argv[2], "wb"); 

    if (out == NULL) 
    { 
    fclose(in); 
    printf("Unable to open '%s' for writing.", argv[2]); 
    } 

    char buffer[BLOCKSIZE]; 
    int count; 

    while (count = fread(buffer, 1, BLOCKSIZE, in)) 
    { 
    int i; 
    for (i = 0; i < count; i++) 
    { 
     ((unsigned long *)buffer)[i] ^= MASK; /* this line is bugged */ 
    } 

    if (fwrite(buffer, 1, count, out) != count) 
    { 
     fclose(in); 
     fclose(out); 
     printf("Cannot write, disk full?\n"); 
     return EXIT_FAILURE; 
    } 
    } 

    fclose(in); 
    fclose(out); 

    return EXIT_SUCCESS; 
} 

Merci pour toute suggestion.

Doug

Répondre

0

Vous aurez également besoin de casser votre masque en morceaux.

unsigned int mask[] = { 0xA37c54f1, 0x73f02889, 0xa64be02f, 0x2bc44112 }; 
unsigned int mask_len = sizeof(mask)/sizeof(*mask); 

Vous aurez alors besoin de travailler avec le tampon que vous lisez dans une série de unsigned int plutôt que les caractères et XOR le morceau contre le morceau approprié du masque:

unsigned int *uint_buffer = (unsigned int *)buffer; 
for (i = 0; i < count/sizeof(int); i++) 
{ 
    uint_buffer[i] ^= mask[i % mask_len]; 
} 

Enfin, selon Sur les détails de votre tâche, vous devrez peut-être gérer les problèmes endian avec les données que vous lisez dans le fichier.

+0

Êtes-vous sûr que 'mask [i]' fonctionnera pour 'count/sizeof (int)'? – Groo

+0

@Groo - vous avez attrapé un bug, je vais mettre à jour mon exemple. –

1

Pas tous (beaucoup?) Plates-formes soutiendront des entiers de 128 bits. Vous pouvez prendre en compte le code qui traite directement les numéros à 128 bits et en écrire deux versions, l'une pour les plates-formes prenant en charge les nombres à 128 bits et l'autre pour celles qui ne le font pas. Un script de configuration peut vérifier le support 128 bits (cochez la case « sizeof(long long) » et « uint128_t », peut-être?) Et de choisir entre les deux implémentations.

2

Mask même « morceaux » avec la première moitié de votre avec l'autre moitié constant et impair « morceaux ».

/* ... */ 
unsigned int xormask[2] = {0xA37c54f173f02889, 0xa64be02f2bc44112}; 
/* ... */ 
     for(i = 0;i < end; ++i) 
     { 
       ((unsigned int *)buffer)[i] ^= xormask[i & 1]; 
     } 
/* ... */ 
2

Promenade à travers votre clé et octet par plaintext octets et effectuer le XOR sur chaque octet séparément.

Change vous clé pour être un tableau d'octets et créer un pointeur vers ce tableau pour faciliter l'utilisation de la clé:

char const key[] = { 
    0xA3, 0x7c, 0x54, 0xf1, 
    0x73, 0xf0, 0x28, 0x89, 
    0xa6, 0x4b, 0xe0, 0x2f, 
    0x2b, 0xc4, 0x41, 0x12 
}; 

char const* pKeyByte = key; 

Ensuite, changez la ligne où vous cryptez de

((unsigned long *)buffer)[i] ^= MASK; /* this line is bugged */ 

à :

buffer[i] ^= *pKeyByte++; 
if (pKeyByte == (key + sizeof(key))) { 
    /* wrap to start of key */ 
    pKeyByte = key; 
} 

Maintenant, vous pouvez changer BLOCKSIZE pour ce que vous voulez votre I/O taille à être, indépendamment de la longueur de la clé. Notez que lorsque vous l'utilisez, BLOCKSIZE définit le nombre d'octets à lire à partir du fichier dans chaque boucle - ce n'est pas le nombre de bits dans la clé.

Notez que le caveats about XOR encryption je dans votre dernière posté question sont encore valables.

+0

Quel est le but de diviser le masque autant et d'ajouter une boucle supplémentaire sur la méthode de pmg? –

+0

Je dirais que cet exemple est un peu plus "universel", vous pouvez changer la longueur de la clé sans avoir besoin de changer quoi que ce soit d'autre. – Groo

+0

Le 'buffer [i + j]' sera surchargé si 'count' n'est pas un multiple de' sizeof (clé) '. Vous devez supprimer la boucle interne et utiliser l'opérateur mod pour indexer le tableau 'key' avec' [i% sizeof (key)] '. – Groo

0

Sur la base de la réponse de Burr, je préférerais ceci:

int i; 
int sizeOfKey = sizeof(key); // key is an array of chars 
for (i = 0; i < count; i++) 
{ 
    buffer[i] ^= key[i % sizeOfKey]; 
} 

Avoir la boucle interne suppose que votre est aligné à 16 octets (c.-à-buffer[i + j] ne vérifie pas la longueur réelle du tampon) .

0

Les tailles de types entiers sont une caractéristique du langage de base. Il ne peut pas être modifié en incluant des bibliothèques. Si vous insistez sur l'utilisation des types intégraux intégrés, la seule façon de surmonter cette limitation est de passer à une autre implémentation qui prend en charge nativement des types entiers plus grands au niveau du langage de base.

Sinon, vous devrez soit scindé votre «longue» constante en deux ou plusieurs constantes «plus courtes», soit utiliser une bibliothèque qui fera exactement la même chose «sous le capot».

Questions connexes