2010-12-14 4 views
4

Ich arbeite an einem Projekt, das 3DES-Verschlüsselung in Java erfordert. Das Problem ist, dass ich mit einem 128-Bit Hex-Schlüssel wie "ABCDEFABCDEF" ausgeliefert wurde (und dies auch weiterhin tun werde). Die Konvertierung in Bytes ist kein Problem. Was ist das Problem ist jedoch, dass die Java Cryptographic Extensions API auf diesen Schlüssel ersticken wird, sagen, dass es ungültig ist. Ich nehme an, dass das MSB jedes Bytes nur ein Paritätsbit ist, also erwartet die JCE, dass ich diese entferne (oder so denke ich). In .NET kann ich jedoch den Schlüssel als geliefert angeben, und es behandelt ruhig die Verschlüsselung/Entschlüsselung ohne Beschwerden.3DES/DES-Verschlüsselung mit dem JCE - Generierung eines akzeptablen Schlüssels

Gibt es eine Möglichkeit, wie ich die Art von Schlüssel generieren kann, den die JCE von der Art des Schlüssels erwartet, den ich bekomme?

Ich habe festgestellt, dass die JCE ermöglicht Ihnen, einen 8-Byte-Schlüssel für DES-Verschlüsselung anzugeben, also habe ich versucht, 3DES als DES EDE mit der Hälfte des mitgelieferten Schlüssels zu implementieren. Ich bekomme jedoch immer noch inkonsistente Ergebnisse mit .NET.

Hier ist der Java-Code:

import javax.crypto.Cipher; 
import javax.crypto.SecretKey; 
import javax.crypto.spec.SecretKeySpec; 
import javax.crypto.spec.IvParameterSpec; 

public class Main{ 
    public static void main(String[] args) throws Exception { 
     byte [] plain = "I eat fish every day".getBytes("utf-8"); 

     byte [] keyBytes = new byte [] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, 
      (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 
      }; 

     byte [] key2Bytes = new byte [] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, 
      (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0 }; // actual keys replaced with dummies. 

     SecretKey keySpec = new SecretKeySpec(keyBytes, "DES"); 
     SecretKey keySpec2 = new SecretKeySpec(key2Bytes, "DES"); 

     IvParameterSpec iv = new IvParameterSpec(new byte[8]); 

     Cipher e_cipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); 
     Cipher cipher = Cipher.getInstance("DES/CBC/NoPadding"); 

     e_cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv); 
     cipher.init(Cipher.DECRYPT_MODE, keySpec2, iv); 

     byte [] cipherText = e_cipher.doFinal(plain); 
     cipherText = cipher.doFinal(cipherText); 
     cipherText = e_cipher.doFinal(cipherText); 

     System.out.println("Ciphertext: " + new sun.misc.BASE64Encoder().encode(cipherText)); 
    } 
} 

und hier ist die .NET-Code:

using System; 
using System.IO; 
using System.Security.Cryptography; 
using System.Text; 

namespace EncryptionDemo 
{ 
    class Program 
    { 
    public static void Main(string[] args) 
    { 
     Console.WriteLine("Hello World!"); 

     // TODO: Implement Functionality Here 
     var plainBytes = Encoding.UTF8.GetBytes("I eat fish every day"); 
     var keyBytes = new byte [] { 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00 }; 

     var tripleDES = TripleDESCryptoServiceProvider.Create(); 
     var transform = tripleDES.CreateEncryptor(keyBytes, new byte [8]); 

     var memStream = new MemoryStream(); 
     var cStream = new CryptoStream(memStream, transform, CryptoStreamMode.Write); 

     cStream.Write(plainBytes, 0, plainBytes.Length); 
     cStream.FlushFinalBlock(); 

     //memStream.Position = 0; 
     var cipherBytes = memStream.ToArray(); 

     Console.WriteLine("Ciphertext: " + Convert.ToBase64String(cipherBytes)); 

     Console.Write("Press any key to continue . . . "); 
     Console.ReadKey(true); 
    } 
} 

Beide unterschiedliche Ausgangssignale erzeugen (einige Zeichen in der Base64-String sind gleich)

+0

"Choke" ist wirklich vage. Wie wäre es mit einer tatsächlichen Fehlermeldung? – erickson

+0

@erickson: Entschuldigung. schauen Sie bitte unter Exception in thread "main" java.security.InvalidKeyException: Ungültige Schlüssellänge: 16 Byte bei com.sun.crypto.provider.DESedeCipher.engineGetKeySize (DashoA13 * ..) \t bei javax.crypto.Cipher. b (DashoA13 * ..) \t bei javax.crypto.Cipher.a (DashoA13 * ..) \t bei javax.crypto.Cipher.a (DashoA13 * ..) \t bei javax.crypto.Cipher.a (DashoA13 * ..) \t bei javax.crypto.Cipher.init (DashoA13 * ..) \t bei javax.crypto.Cipher.init (DashoA13 * ..) \t bei Main.main (Main.java:30) – darkphoenix

+0

Zur Kontextklärung, die Frage kommt aus der jpos Mailing-Liste https://groups.google. com/forum/#! msg/jpos-users/sfXGf2gwQhY/xN63ze305bwJ – bbozo

Antwort

1

Der Sun-Anbieter akzeptiert keine 16-Byte-3DES-Schlüssel, aber der BouncyCastle-Anbieter tut dies. Ich habe es einfach ausprobiert und es funktioniert wie ein Zauber - es produziert die gleiche Ausgabe wie der .NET-Code!

import javax.crypto.Cipher; 
import javax.crypto.SecretKey; 
import javax.crypto.spec.SecretKeySpec; 
import javax.crypto.spec.IvParameterSpec; 
import java.security.Security; 

import org.bouncycastle.jce.provider.BouncyCastleProvider; 

public class Main{ 
    public static void main(String[] args) throws Exception { 
     Security.addProvider(new BouncyCastleProvider()); 

     byte [] plain = "I eat fish every day".getBytes("utf-8"); 

     byte [] keyBytes = new byte [] { (byte) 0xC1, (byte) 0x57, (byte) 0x45, (byte) 0x08, 
      (byte) 0x85, (byte) 0x02, (byte) 0xB0, (byte) 0xD3, 
      (byte) 0xA2, (byte) 0xEF, (byte) 0x68, (byte) 0x43, 
      (byte) 0x5E, (byte) 0xE6, (byte) 0xD0, (byte) 0x75 }; 


     SecretKey keySpec = new SecretKeySpec(keyBytes, "DESede"); 

     IvParameterSpec iv = new IvParameterSpec(new byte[8]); 

     Cipher e_cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding", "BC"); 

     e_cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv); 

     byte [] cipherText = e_cipher.doFinal(plain); 

     System.out.println("Ciphertext: " + new sun.misc.BASE64Encoder().encode(cipherText)); 
    } 
} 
4

3DES Schlüssel sind 192 Bits lang.

Wie erstellen Sie die SecretKey Instanz? Welche Fehlermeldung erhalten Sie?


Der Java-Code in Ihre Frage wird mit DES, nicht "Triple DES". Der Name des Algorithmus sollte "DESede/CBC/PKCS5Padding" sein. Der Code in deiner Antwort funktioniert wahrscheinlich, weil du den Algorithmus richtig verstanden hast, nicht weil du Anbieter gewechselt hast. Der SunJCE-Provider in Java 6 akzeptiert 128-Bit-Schlüssel (und verwendet Keying-Option 2). Ich bin mir nicht sicher über ältere Versionen.

+1

3DES Schlüsselring Option 2 verwendet 128 Bits (oder 112 Bits, wenn Sie die Parität weglassen) - k1 und k3 sind gleich. Vielleicht nutzt das sein Projekt? Der JCE scheint 112-Bit-3DES-Schlüssel zu unterstützen. Es scheint auch von den Dokumenten zu sein, dass JCE die Paritätsbits entfernen möchte (dh 112 oder 168 Bits, nicht 128 oder 192). –

+0

Es kommt auf den Anbieter an. Das SunJCE akzeptiert einen 128-Bit-Schlüssel (112-Bit-aktuelles Schlüsselmaterial), aus dem hervorgeht, dass Sie die Schlüsseloption 2 verwenden möchten. Andere Anbieter unterstützen möglicherweise nur die (sicherere) Schlüsseloption 1, die 192 Bit erfordert. Die Paritätsbits müssen im Schlüssel * enthalten * sein. – erickson

+0

Bitte den eingefügten Code über – darkphoenix

1

Im jPOS Projekt wird das Problem umgangen, indem sie immer entweder einzelne Länge (8 Byte) oder dreifache Länge (24-Byte) Tasten. Angenommen, Ihr eindeutiger Schlüssel mit doppelter Länge (in Byte) ist AAAAAAAA BBBBBBBB. Der gesamte Code im jPOS-Projekt, den ich bisher gesehen habe und der das JCE verwendet, hängt die ersten 8 Bytes wieder an den Clear-Key an, so dass es ein dreifacher Schlüssel wird: AAAAAAAA BBBBBBBB AAAAAAAA. Es scheint, dass der Sun-Anbieter dieses Material zum Erstellen einer SecreKeySpec akzeptiert, da es 192 Bit lang ist, wie @erickson erwähnt hat.

Verwandte Themen