DESアルゴリズムの詳細

6040 ワード

JAVAと.NETのシステムクラスライブラリにはDES対称暗号化をカプセル化する実装方式があるが、外部に露出するインタフェースはそれぞれ異なり、JAVA暗号化後の結果など、その問題を解決することが難しい場合もある.NETでは解読できないなど、
DES暗号化
DESは対称暗号化(Data Encryption Standard)アルゴリズムで、以前私は1篇の文章を書いたことがあります:.NETでは暗号解読に関する知識を簡単に説明しています.
DESアルゴリズムには一般的に2つのキーがあり、1つ目は暗号化アルゴリズムであり、2つ目はデータ補位である.
暗号化アルゴリズムによく見られるのはECBモードとCBCモードです.
ECBモード:電子暗号方式、これはJAVAパッケージのDESアルゴリズムのデフォルトモードであり、データを8バイトずつDES暗号化または復号して8バイトの暗号文または明文を得、最後のセグメントは8バイト未満であり、8バイト(ここではデータ補完について説明します)を足して計算し、その後、計算したデータを順番に連結すればよく、各セグメントのデータ間は互いに影響しません.
CBCモード:暗号文パケットリンク方式、これは.NETパッケージのDESアルゴリズムのデフォルトモードは、面倒で、暗号化の手順は以下の通りです.
1、まずデータを8バイトずつグループ化してD 1 D 2を得る…Dn(データが8の整数倍でなければデータ補正にかかわる)
2、第1グループデータD 1がベクトルIと異なるか否かの結果DES暗号化を行って第1グループの暗号文C 1を得る(ここではベクトルIの説があり、ECBモードではベクトルIは使用されていない)
3、第2グループのデータD 2は、第1グループの暗号化結果C 1と異なるか以降の結果としてDES暗号化を行い、第2グループの暗号文C 2を得る
4、その後のデータはこのようにして、Cnを得る
5、順番にC 1 C 2 C 3につながる…Cnは暗号化の結果です.
データ補位は一般的にNoPaddingとPKCS 7 Padding(JAVAではPKCS 5 Padding)の充填方式があり、PKCS 7 PaddingとPKCS 5 Paddingは実際にはプロトコルが異なるだけで、関連資料の説明によると、PKCS 5 Paddingは暗号化ブロックが8バイトであることを明確に定義し、PKCS 7 Paddingの暗号化は1-255の間であることができる.しかし,パッケージされたDESアルゴリズムはデフォルトでは8バイトであるため,同様と考えられる.データ補位は、実際には、データが8バイト未満の倍数であってこそ、8バイトの倍数に補完される充填プロセスである.
NoPadding充填方式:アルゴリズム自体は充填しない、例えば.NETのpaddingはNone,Zeros方式を提供し,それぞれ0を充填しない方式と充填する方式である.
PKCS 7 Padding(PKCS 5 Padding)パディング方式:.NETとJAVAのデフォルトパディング方式であり、暗号化データのバイト長を8に対して余剰をrとし、rが0より大きい場合は8-rバイトを補い、バイトは8-rの値を補い、rが0に等しい場合は8バイト8を補います.例えば:
暗号化文字列がAAAであれば、補位はAAA 55555である.暗号化文字列がBBBBBBであれば、補位はBBBBBBBB 22である.暗号化文字列がCCCCCCであれば、補位はCCCCCC 888888である.
.NETでのDES暗号化
はい.NET、フレームワークはSystem.Security.Cryptographyネーミングスペースには、システムとしてDESCryptoServiceProviderが用意されています.Security.Cryptography.DES暗号解読のパッケージインタフェースは、以下の4つの方法を提供します.
public override ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[] rgbIV)
public override ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[] rgbIV)
public override void GenerateIV()
public override void GenerateKey()

からNETクラスライブラリのカプセル化の場合,復号化にはKeyとIVベクトルが必要である.また、Keyは8バイトのデータでなければなりません.そうしないと、異常が直接放出されます.ECBモードを使用すると、IVベクトルがどのように入力されても、暗号化結果は同じです.サンプルコードは次のとおりです.
     
  public static string EncryptWithJava(string key, string str)
        {
            if (key.Length < 8 || string.IsNullOrEmpty(str))
            {
                throw new Exception("  key  8         !");
            }
            byte[] bKey = Encoding.UTF8.GetBytes(key.Substring(0, 8));
            byte[] bIV = IV;
            byte[] bStr = Encoding.UTF8.GetBytes(str);
            try
            {
                DESCryptoServiceProvider desc = new DESCryptoServiceProvider();
                desc.Padding = PaddingMode.PKCS7;//  
                desc.Mode = CipherMode.ECB;//CipherMode.CBC
                using (MemoryStream mStream = new MemoryStream())
                {
                    using (CryptoStream cStream = new CryptoStream(mStream, desc.CreateEncryptor(bKey, bIV), CryptoStreamMode.Write))
                    {
                        cStream.Write(bStr, 0, bStr.Length);
                        cStream.FlushFinalBlock();
                        StringBuilder ret = new StringBuilder();
                        byte[] res = mStream.ToArray();
                        foreach (byte b in res)
                        {
                            ret.AppendFormat("{0:x2}", b);
                        }
                        return ret.ToString();
                    }
                }
            }
            catch
            {
                return string.Empty;
            }
        }

ECBモードであるため、IVはここではどの値を設定してもよいが、CBCモードであれば、public static byte[IV={0 x 01,0 x 02,0 x 03,0 x 04,0 x 05,0 x 06,0 x 07,0 x 08}のような他の値に設定する必要がある.
JAVAでのDES暗号化
JAVAのjavax.crypto.Cipherパッケージの下には、暗号解読機能があり、その静的getInstanceメソッドは、一般的にpublic static final Cipher getInstance(String transformation)メソッドがあり、transformationは:
Algorithm/mode/paddingは、それぞれアルゴリズム名、例えばDESを表し、後にアルゴリズムモードや塗り方を含んでもよいが、「DES/CBC/PKCS 5 Padding」、「DES」などのアルゴリズム名のみであってもよい.
JAVAのデフォルトのアルゴリズムはECBで、デフォルトの塗り方はPKCS 5 Paddingです.CipherのInitメソッドは、暗号化されたオブジェクトを初期化するために使用されます.
public final void init(int opmode, Key key, AlgorithmParameterSpec params) ,
public final void init(int opmode,Key key, SecureRandom random)
、SecureRandomを使用する場合、IVを必要としないアルゴリズムモードに一般的に使用されます.サンプルコードは以下の通りです.
public static String encrypt2(String src) throws Exception {
       SecureRandom sr = new SecureRandom();
       DESKeySpec ks = new DESKeySpec(KEY.getBytes("UTF-8"));
       SecretKeyFactory skf = SecretKeyFactory.getInstance("DES");
       SecretKey sk = skf.generateSecret(ks);
       Cipher cip = Cipher.getInstance("DES/CBC/PKCS5Padding");//Cipher.getInstance("DES");
       IvParameterSpec iv2 = new IvParameterSpec(IV);
       cip.init(Cipher.ENCRYPT_MODE, sk, iv2);//IV   
       //cip.init(Cipher.ENCRYPT_MODE, sk, sr);//    IV
       String dest = byteToHex(cip.doFinal(src.getBytes("UTF-8")));
       return dest;
    }

デフォルトでDESを使用する場合、JAVAはECBモードを使用するため、ここではIVベクトルは機能しないが、ここではCBCモードでもSecureRandomを使用する場合、暗号化の結果は毎回異なる.JAVA内部では、サンプルコードのようにランダムなIVでCipherオブジェクトを初期化するため、
Cipher.getInstance("DES/CBC/PKCS5Padding")   CBC,       javax.crypto.spec.IvParameterSpec   IvParameterSpec      IV:
Private final static byte[] IV = new byte[] {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
 

まとめ
はい.NETとJAVAはDES対称暗号化を使用する場合、同じアルゴリズムとパディングモードを指定する必要があり、JAVAはDES復号アルゴリズムを書く場合、Cipherオブジェクトを作成することによってIVベクトルを正しく使用する必要がある.異なるシステムで相互データを必要とする場合,暗号化アルゴリズム,Key,アルゴリズムモードを明確にし,さらに異なるモードによってIVベクトルが必要かどうか,最後に充填モードである必要がある.