2010-12-14 6 views
4

私はプロジェクトで、が必要です。 Javaの3DES暗号化です。問題は、私が "ABCDEFABCDEF"のような128ビットの16進数キーを入力していたことです。バイトへの変換は問題ありません。 ですが、Java Cryptographic Extensions APIが無効であると言って、このキーを詰まらせるという問題があります。私は、各バイトのMSBが単にパリティビットであることを知っているので、JCEはそれらを取り除くことを期待しています。しかし、.NETでは、指定したキーを指定することができ、苦情のない暗号化/復号化を静かに処理します。JCEを使用した3DES/DES暗号化 - 受け入れ可能な鍵の生成

JCEが提供しているキーの種類から期待している種類のキーを生成する方法はありますか?

私は、JCEがDES暗号化用に8バイトのキーを指定できることを知りました。そのため、提供されたキーの半分を使用して3DESをDES EDEとして実装しようとしました。しかし、私はまだ.NETで矛盾した結果を得ています。

は、ここでのJavaコードです:

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)); 
    } 
} 

、ここ.NETコードです:両方が異なる出力(Base64文字列の一部の文字が同じである)を生成

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); 
    } 
} 

+0

「チョーク」は実際には曖昧です。実際のエラーメッセージはどうですか? – erickson

+0

@erickson:申し訳ありません。以下を参照してください スレッド "main"の例外java.security.InvalidKeyException:無効なキーの長さ:com.sun.crypto.provider.DESedeCipher.engineGetKeySize(DashoA13 * ..)の16バイト。 \t(javax.crypto.Cipher)。 b(DashoA13 * ..) \t、javax.crypto.Cipher.a(DashoA13 * ..)javax.crypto.Cipher.aで) javax.crypto.Cipher.aで\t(DashoA13 * ...) \t(javax.crypto.Cipher.initでDashoA13 * ...) \t(DashoA13 * ...) \t at javax.crypto.Cipher.init(DashoA13 * ..) \t at Main.main(Main.java:30) – darkphoenix

+0

文脈を明確にするため、質問はjposメーリングリストhttps://groups.googleから得られます。 #/ msg/jpos-users/sfXGf2gwQhY/xN63ze305bwJ – bbozo

答えて

1

Sunプロバイダは16バイトの3DESキーを受け付けませんが、BouncyCastleプロバイダは受け入れます。私はちょうどそれを試してみて、それは魅力のように動作します - それは.NETコードと同じ出力を生成します! jPOSプロジェクトで

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キーの長さは192ビットです。

SecretKeyインスタンスの作成方法を教えてください。どのようなエラーメッセージが表示されますか?


あなた質問でのJavaコードはDESではなく、 "トリプルDES" を使用しています。アルゴリズム名は"DESede/CBC/PKCS5Padding"である必要があります。 のコードは、アルゴリズムを正しく取得したために機能している可能性があります。プロバイダを切り替えたわけではありません。 Java 6のSunJCEプロバイダは、128ビットのキーを受け入れます(キーイングオプション2を使用します)。私は古いバージョンについてはわかりません。

+1

3DESキーリングオプション2は128ビット(パリティを省略した場合は112ビット)を使用します.k1とk3は同じです。多分それは彼のプロジェクトが使用しているものでしょうか? JCEは112ビットの3DESキーをサポートしているようです。また、JCEはパリティビットを削除したいと考えているようです(つまり、128または192ではなく、112または168ビット)。 –

+0

プロバイダによって異なります。 SunJCEは、キーイングオプション2が必要であると推測する128ビットキー(112ビットの実際のキーイングマテリアル)を受け入れます。他のプロバイダは、192ビットを必要とする(より安全な)キーイングオプション1のみをサポートします。パリティビットは、キーに含まれていなければなりません。 – erickson

+0

上記の貼り付けられたコードを参照してください – darkphoenix

1

、問題は、常に単一の長さ(8バイト)又は三重長(24バイト)キーのいずれかを使用することによって回避されます。あなたのクリア・ダブル・レングス・キー(バイト単位)がAAAAAAAA BBBBBBBBだとしましょう。これまでJCEを使用していたjPOSプロジェクトのすべてのコードは、最初の8バイトをクリアキーに再度追加するため、AAAAAAAA BBBBBBBB AAAAAAAAのように3倍の長さのキーになります。 @ericksonが述べたように、Sunのプロバイダは、SecreKeySpecを作成するためにこの資料を受け入れると思われます。

関連する問題