3 Stimmen

Bitmanipulation von Zeichen in Java oder C?

Ich bin ein Student, der versucht, den DES-Algorithmus zu implementieren. Ich habe die Wahl zwischen 2 Sprachen: C und Java. Ich habe den Algorithmus verstanden, aber ich stecke ganz am Anfang fest, was die Manipulation des Schlüssels angeht.

Hier ist das Problem. In DES haben wir einen 64-Bit-Schlüssel (8 Zeichen in C und 4 in Java, obwohl ich das Zeichen in Byte umwandeln kann, um nur den ASCII-Teil zu erhalten), von dem jedes achte Bit ein Paritätsbit ist und gestrippt werden muss, um einen 56-Bit-Schlüssel daraus zu machen und weiter zu verarbeiten. Ich habe lange darüber nachgedacht, kann aber keine Möglichkeit finden, jedes 8. Bit zu entfernen und das Ergebnis in einem anderen char-Array zu speichern (sowohl in Java als auch in C). Ich habe es mit dem java.util.BitSet class aber ich war verwirrt.

Gibt es Vorschläge, wie ich jedes 8. Bit entfernen und benachbarte Bytes (Java) oder Zeichen (C) zusammenfügen kann, um den 56-Bit-Schlüssel zu erhalten?

Ich bin mir der Bitoperationen und der Verschiebung bewusst, aber für das konkrete Beispiel:
Angenommen, ich habe einen 16-Bit-Schlüssel: 1100 1001 1101 1000 .
Ich muss das 8. und 16. Bit entfernen, um den Schlüssel herzustellen: 1100 100 1101 100 .

Wenn ich 2 Bytes deklariere, wie schneide ich das 8. Bit ab und hänge das 9. Bit an, wodurch das erste Byte entsteht: 1100 1001

Ich brauche also Hilfe bei der Frage, wie ich das 8. Bit durch das 9. Bit, das 16. Bit durch das 17. Bit usw. ersetzen kann, um einen 56-Bit-Schlüssel aus einem 64-Bit-Schlüssel abzuleiten.

Wenn mir das jemand erklären kann, kann ich es vielleicht unabhängig von der Sprache umsetzen.

3voto

rossum Punkte 14800

Seien Sie vorsichtig mit 16-Bit-Zeichen in Java. Viele Methoden konvertieren nur die unteren 8 Bits. Lesen Sie die Dokumentation sorgfältig. Es ist üblicher, einen kryptographischen Schlüssel als einen byte[] in Java aufgrund der stärkeren Typisierung als in C.

Was die Paritätsbits anbelangt, so sollten Sie den DES-Algorithmus genau durchlesen und nachsehen, wo sie verwendet werden. Das sollte Ihnen einen Hinweis darauf geben, was Sie mit ihnen tun müssen.

1voto

jwd Punkte 10217

In C können Sie Bits mit den bitweisen Operatoren manipulieren, z. B. & y | sowie die Bitshift-Operatoren << y >> .

Um zum Beispiel das High-Bit eines bestimmten Bytes auszuschalten, können Sie Folgendes tun.

char c = 0xBF;  // initial value is bit pattern 10111111
c &= 0x7F;      // perform AND against the bit pattern 01111111
                // final value is bit pattern 00111111 (0x3F)

Ergibt das einen Sinn? Natürlich müssen Sie in der Lage sein, ein Bitmuster in Hexadezimal zu konvertieren, aber das ist nicht allzu schwer.

Sie können eine ähnliche Maskierung verwenden, um die gewünschten Bits zu extrahieren und sie in einen Ausgabepuffer zu legen.

Update:

Sie haben 64 Bit (8 Byte) Eingabe und wollen 56 Bit (7 Byte) Ausgabe.

Stellen wir uns Ihre Eingabe wie folgt vor, wobei jeder Buchstabe für ein einzelnes Bit steht Die 'x' Bits sind diejenigen, die Sie wegwerfen wollen.

xAAAAAAA xBBBBBBB xCCCCCCC xDDDDDDD xEEEEEEE xFFFFFFF xGGGGGGG xHHHHHHH

Sie wollen also, dass Ihre endgültige Antwort lautet:

AAAAAAAB BBBBBBCC CCCCCDDD DDDDEEEE EEEFFFFF FFGGGGGG GHHHHHHH

In C könnten wir also einen Code wie diesen haben:

unsigned char data[8] = {/* put data here */};

// chop off the top bit of the first byte
data[0] <<= 1;

// the bottom bit of data[0] needs to come from the top data bit of data[1]
data[0] |= (data[1] >> 6) & 0x01;

// use similar transformations to fill in data[1], data[2], ... data[6]
// At the end, data[7] will be useless

Natürlich ist das alles nicht optimal, aber ich hoffe, Sie verstehen die Idee.

0voto

jscode Punkte 173

Ich kann kurz über einen Weg erzählen....i wird bei Bedarf weiter erklären...

Rechtsverschiebung aller 8 Zeichen um 1, d. h. c1 = c1>>1 usw.

Multiplizieren Siec1 mit der Gesamtzahl der Bytes (d.h. 56), d.h. c1 * 0x0000000000 (ich bin nicht sicher, wie viele Nullen)

Dann fügen Sie 0x0000+ zu den nächsten Zeichen hinzu, d. h. c2 = c2 + 0x0000; c3 = c3 + 0x000000 usw. (fügen Sie immer 2 0en für die weiteren Zeichen hinzu)

Beginnen Sie nun mit der Addition von c1 + c2 + c3.......

Die Idee dabei ist, dass man zuerst die Zahl mit Nullen auffüllt und dann die anderen Zeichen hinzufügt, damit sie richtig liegen bleiben

00 00 00 00 00 00 00 00 00
34 00 00 00 00 00 00 00 00   (c1 = c1>>1) . Here c1=0x34, c2=0x67
00 67 00 00 00 00 00 00 00   (c2 = c2>>1)
so on...............

Fügen Sie das Obige hinzu; Ich hoffe, das hilft.

0voto

krish7919 Punkte 864

@jwd, @jscode Vielen Dank für Ihre Hilfe. An jwd: Ich habe die Idee von deinem Code. Schien mir ziemlich einfach zu sein, nachdem ich ihn gelesen hatte :-) Ich frage mich, warum ich nicht daran gedacht habe. Nun, ich habe deine Idee ein wenig verfeinert und sie funktioniert jetzt gut in Java. Wenn jemand einen Vorschlag hat, bitte ich um Mitteilung. DANKE. P.S.: Der Testteil ist sehr primitiv. Ich drucke die Bit-Werte aus. Ich habe es manuell für ein paar Beispiele gemacht und das gleiche als Eingabe verwendet und es funktioniert gut.

\=============================================

public static void main(String[] args) {

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        System.out.println("Enter an 8 char key: ");
        String input;
        try {
            // get key, key.length()>=8 chars
            input = br.readLine();
            if (input.length() < 8) {
                System.out.println("Key < 8B. Exiting. . .");
                System.exit(1);
            }
            // java char has 16 bits instead of 8 bits as in C,
            // so convert it to 8 bit char by getting lower order byte &
            // discarding higher order byte
            char[] inputKey = input.toCharArray();
            byte[] key64 = new byte[8];
            byte[] key56 = new byte[7];

            // consider only first 8 chars even if input > 8
            for (int counter = 0; counter < 8; counter++)
                key64[counter] = (byte) inputKey[counter];

            System.out.print("\n$$ " + new String(key64) + "  $$\n");

            // converting 64bit key to 56 bit key
            for (int counter = 0; counter < KEY_LENGTH - 1; counter++) {
                key64[counter] = (byte) (key64[counter] >>> 1);
                key64[counter] = (byte) (key64[counter] << 1);
            }

            for (int counter = 0; counter < KEY_LENGTH - 1; counter++) {
                key56[counter] = (byte) (key64[counter] << counter);
                key56[counter] = (byte) (key56[counter] | (key64[counter + 1] >>> (KEY_LENGTH - 1 - counter)));
            }

            /*Conversion from 64 to 56 bit testing code
             System.out.println(new String(key56));

            System.out.println();
            for (int counter1 = 0; counter1 < 7; counter1++) {
                for (int counter2 = 7; counter2 >= 0; counter2--) {
                    System.out.println(key56[counter1] & (1 << counter2));
                }
                System.out.println();
            }*/

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X