Cosa c’è di male nello spostamento di 32 bit variabili a 32 bit?

Recentemente ho preso una copia di Applied Cryptography di Bruce Schneier ed è stata una buona lettura. Ora capisco come funzionano diversi algoritmi delineati nel libro e vorrei iniziare a implementarne alcuni in C.

Una cosa che molti degli algoritmi hanno in comune è la divisione di una chiave x-bit, in diversi tasti y-bit più piccoli. Ad esempio, la chiave di Blowfish, X, è a 64 bit, ma è necessario suddividerla in due metà a 32 bit; Xl e Xr.

Questo è dove mi sto bloccando. Sono abbastanza decente con C, ma non sono il più forte quando si tratta di operatori bit a bit e simili.

Dopo un po ‘di aiuto su IRC, sono riuscito a trovare questi due macro:

#define splitup(a, b, c) {b = a >> 32; c = a & 0xffffffff; } #define combine(a, b, c) {a = (c << 32) | a;} 

Dove a è 64 bit e bec sono 32 bit. Tuttavia, il compilatore mi avvisa del fatto che sto spostando una variabile a 32 bit di 32 bit.

Le mie domande sono queste:

  • Cosa c’è di male nello spostamento di 32 bit variabili a 32 bit? Sto indovinando che non è definito, ma queste macro sembrano funzionare.
  • Inoltre, suggeriresti di andare in un altro modo?

Come ho detto, ho una certa familiarità con C, ma gli operatori bit a bit e simili mi danno ancora fastidio.

MODIFICARE

Ho capito che la mia macro combinata in realtà non combinava due variabili a 32 bit, ma semplicemente ORing 0 di ae ottenendo un risultato.
Quindi, in aggiunta alle mie precedenti domande, non ho ancora un metodo per combinare le due variabili a 32 bit per ottenere uno a 64 bit; un suggerimento su come farlo sarebbe apprezzato.

Sì, è un comportamento indefinito.

ISO / IEC 9899: 1999 6.5.7 Operatori di spostamento bit a bit ¶3

Le promozioni intere vengono eseguite su ciascuno degli operandi. Il tipo del risultato è quello dell’operando sinistro promosso. Se il valore dell’operando di destra è negativo o è maggiore o uguale alla larghezza dell’operando di sinistra promosso, il comportamento non è definito.

C11 alias ISO / IEC 9899: il 2011 dice lo stesso.

Dovresti prima convertire b nel tipo di intero target. Un altro punto è che dovresti mettere parentesi attorno ai parametri macro per evitare sorprese da parte delle precedenze degli operatori. Inoltre, l’operatore virgola è molto utile qui, consentendo di evitare le parentesi graffe, in modo che la macro possa essere utilizzata come un normale comando, chiusa da un punto e virgola.

 #define splitup(a,b,c) ( (b) = (a) >> 32, (c) = (a) & 0xffffffff ) #define combine(a,b,c) ( (a) = ((unsigned long long)(b) << 32) | (c) ) 

Potrebbero essere necessari cast aggiuntivi per `splitup 'per tacitare gli avvertimenti sulla perdita di precisione da parte di compilatori sovraparanoidi.

 #define splitup(a,b,c) ( (b) = (unsigned long)((a) >> 32), (c) = (unsigned long)((a) & 0xffffffff) ) 

E per favore non pensate nemmeno di usare la vostra crittografia auto-scritta per il codice di produzione.

Spostare un valore a 32 bit di 32 bit o più non è definito in C e C ++. Uno dei motivi per cui è stato lasciato indefinito è che su alcune piattaforms hardware l’istruzione di spostamento a 32 bit prende in considerazione solo 5 bit più bassi del numero di shift fornito. Ciò significa che qualunque sia il numero di turni che si passa, verrà interpretato come modulo 32. Il tentativo di spostare per 32 su tale piattaforma si sposterà effettivamente di 0, cioè non cambierà affatto.

Gli autori del linguaggio non volevano appesantire i compilatori scritti per tale piattaforma con il compito di analizzare il conteggio dei turni prima di effettuare il turno. Invece, le specifiche del linguaggio dicono che il comportamento non è definito. Ciò significa che se si desidera ottenere un valore 0 da uno spostamento a 32 bit per 32 (o più), spetta a te riconoscere la situazione ed elaborarla di conseguenza.

cosa c’è di male nello spostamento di 32 bit a 32 bit variabili?

È meglio assegnare da 0 a numero intero n-bit che spostarlo per n-bit.

Esempio:

  0 0 1 0 1 ----- 5 bit Integer 0 1 0 1 0 ----- 1st shift 1 0 1 0 0 ----- 2nd shift 0 1 0 0 0 ----- 3rd shift 1 0 0 0 0 ----- 4th shift 0 0 0 0 0 ----- 5th shift (all the bits are shifted!) 

Non ho ancora un metodo per combinare le due variabili a 32 bit per ottenere uno a 64 bit

Considerare: a è 64 bit, b e c sono 32 bit

 a = b; a = a << 32; //Note: a is 64 bit a = a | c; 

A meno che non si tratti di un progetto di “reinventare la ruota per capire come funziona”, non implementare le proprie funzioni crittografiche.

Mai.

È abbastanza difficile usare gli algoritmi disponibili per lavorare (e scegliere quello giusto), non sparare ai piedi mettendo in produzione alcune API Cryptor native. È probabile che la crittografia non venga crittografata

Cosa c’è di male nello spostamento di 32 bit variabili a 32 bit?

Oltre a ciò che è stato già detto, il 32 ° bit è il bit del segno e potresti ottenere l’estensione del segno per preservare il canto, perdendo così dei bit significativi.