Java SE での 共通鍵暗号

package com.snail.example;

import sun.misc.HexDumpEncoder;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.SecretKeySpec;


/**
 * Common Key Cipher Examination.
 *
 * @author kagyuu
 * @version $Revision$
 */
public class ComKeyExam {
  /** Example plain document */
  private static String example = "Wisdoms -"
    + "Insanity: doing the same thing over and over again and expecting "
    + "different results." + "Albert Einstein"
    + "Happiness is nothing more than good health and a bad memory."
    + "Albert Schweitzer"
    + "Our problems are man-made, therefore they may be solved by man. "
    + "J.F.K"
    + "Obstacles are those frightful things you see when you take your "
    + "eyes off your goal. " + "Henry Ford";

  /** dump binary data */
  private static HexDumpEncoder hexDump = new HexDumpEncoder();

  /**
   * Main Routine
   *
   * @param args Commandline Argument
   */
  public static void main(String[] args) {
    try {
      // Generate Key
      SecretKey desKey = KeyGenerator.getInstance("DES").generateKey();
      encryptAndDecrypt(desKey);
      // Read Key
      encryptAndDecrypt(readDESKey());
      encryptAndDecrypt(read3DESKey());
      encryptAndDecrypt(readAES128Key());

      // DON'T WORK ON JAVA 6
      // encryptAndDecrypt(readAES192Key());
      // encryptAndDecrypt(readAES256Key());
    } catch (Exception ex) {
      ex.printStackTrace();
    }
  }

  /**
   * encrypt and decrypt text
   *
   * @param key Key
   *
   * @throws NoSuchAlgorithmException DOCUMENT ME!
   * @throws NoSuchPaddingException DOCUMENT ME!
   * @throws InvalidKeyException DOCUMENT ME!
   * @throws IllegalBlockSizeException DOCUMENT ME!
   * @throws BadPaddingException DOCUMENT ME!
   */
  private static void encryptAndDecrypt(SecretKey key)
    throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
      IllegalBlockSizeException, BadPaddingException {
    System.out.println(key.getAlgorithm() + "," + key.getFormat());
    System.out.println(hexDump.encode(key.getEncoded()));
    // Raw data
    System.out.println("\nRAW DATA");

    byte[] rawText = example.getBytes();
    System.out.println(hexDump.encode(rawText));

    Cipher cipher = Cipher.getInstance(key.getAlgorithm() + "/ECB/PKCS5Padding");

    // Encrypt data
    cipher.init(Cipher.ENCRYPT_MODE, key);

    byte[] encryptedText = cipher.doFinal(rawText);
    System.out.println("\nENCRYPTED DATA");
    System.out.println(hexDump.encode(encryptedText));

    // Decrypt data
    cipher.init(Cipher.DECRYPT_MODE, key);

    byte[] decryptedText = cipher.doFinal(encryptedText);
    System.out.println("\nEDERYPTED DATA");
    System.out.println(hexDump.encode(decryptedText));
  }

  /**
   * create 3DES Key
   *
   * @return 3DES Key
   *
   * @throws InvalidKeyException something wrong
   * @throws InvalidKeySpecException something wrong
   * @throws NoSuchAlgorithmException something wrong
   */
  private static SecretKey read3DESKey()
    throws InvalidKeyException, InvalidKeySpecException,
      NoSuchAlgorithmException {
    byte[] key = "3DESIsEncrypt3timesByDES".getBytes(); // 24byte(192bit)

    return SecretKeyFactory.getInstance("DESEde")
                           .generateSecret(new DESedeKeySpec(key));
  }

  /**
   * Create 128bit length AES Key
   *
   * @return AES Key
   *
   * @throws InvalidKeySpecException something wrong
   * @throws NoSuchAlgorithmException something wrong
   */
  private static SecretKey readAES128Key()
    throws InvalidKeySpecException, NoSuchAlgorithmException {
    byte[] key = "AESIsFipsPub197.".getBytes(); // 16byte(128bit)

    return new SecretKeySpec(key, "AES");
  }

  /**
   * Create 192bit length AES Key.
   * DON'T WORK ON JAVA 6
   *
   * @return AES Key
   *
   * @throws InvalidKeyException something wrong
   * @throws InvalidKeySpecException something wrong
   * @throws NoSuchAlgorithmException something wrong
   */
  private static SecretKey readAES192Key()
    throws InvalidKeyException, InvalidKeySpecException,
      NoSuchAlgorithmException {
    byte[] key = "Rijndael catched on AES.".getBytes(); // 24byte(192bit)

    return new SecretKeySpec(key, "AES");
  }

  /**
   * Create 256bit length AES Key.
   * DON'T WORK ON JAVA 6
   *
   * @return AES Key
   *
   * @throws InvalidKeySpecException something wrong
   * @throws NoSuchAlgorithmException something wrong
   */
  private static SecretKey readAES256Key()
    throws InvalidKeySpecException, NoSuchAlgorithmException {
    byte[] key = "AESIsAdvancedEncryptionStandard.".getBytes(); // 32byte(256bit)

    return new SecretKeySpec(key, "AES");
  }

  /**
   * Create DES Key
   *
   * @return DES Key.
   *
   * @throws InvalidKeyException something wrong.
   * @throws InvalidKeySpecException something wrong.
   * @throws NoSuchAlgorithmException something wrong.
   */
  private static SecretKey readDESKey()
    throws InvalidKeyException, InvalidKeySpecException,
      NoSuchAlgorithmException {
    byte[] key = "password".getBytes(); // 8byte(64bit)

    return SecretKeyFactory.getInstance("DES")
                           .generateSecret(new DESKeySpec(key));
  }
}

利用できる暗号アルゴリズム

  1. 暗号アルゴリズム
    DESData Encryption Standard。鍵長は64bit (8bit毎に1bitのパリティが付くので実質56bit)
    DESEdeDESを3回施す暗号方式。鍵長は192bit
    AESAdvanced Encryption Standard。鍵長は128bit、192bit、256bit
  2. Block Mode
    NONEなし
    CBCFIPS PUB 81。Cipher Block Chaining Mode
    CFBFIPS PUB 81。Cipher Feedback Mode
    ECBFIPS PUB 81。Electronic Codebook Mode。米国商務省標準「DES Modes of Operation」
    OFBFIPS PUB 81。Output Feedback Mode
    PCBCKerberos Version 4。Propagating Cipher Block Chaining
  3. Padding Mode
    NoPadding?なし
    ISO10126PaddingW3C形式
    OAEPWith<digest>And<mgf>PaddingPKCS #1
    PKCS5PaddingPKCS #5
    SSL3PaddingSSL Protocol Version 3.0

AES暗号の実装について

  1. 128bir長しか使えない
    192bit、256bit長の鍵を使おうとすると InvalidKeyException? が発生する
    java.security.InvalidKeyException: Illegal key size or default parameters
    	at javax.crypto.Cipher.a(DashoA13*..)
    	at javax.crypto.Cipher.a(DashoA13*..)
    	at javax.crypto.Cipher.a(DashoA13*..)
    	at javax.crypto.Cipher.init(DashoA13*..)
    	at javax.crypto.Cipher.init(DashoA13*..)
    	at com.snail.example.ComKeyExam.encryptAndDecrypt(ComKeyExam.java:88)
    	at com.snail.example.ComKeyExam.main(ComKeyExam.java:57)
     
  2. キーの作り方が DES と違う
    • DESでは、KeySpec? から Keyを作る
      SecretKey key = SecretKeyFactory.getInstance("DES").generateSecret(new DESKeySpec(key));
       
    • AESでは、SecretKeyFactory? 経由では SecretKey? を作れない
      SecretKey key = SecretKeyFactory.getInstance("AES").generateSecret(new SecretKeySpec(key, "AES"));
      は実行時エラーが起きる
       
    • AESでは、SecretKeySpec?SecretKey? として使う
      SecretKey key = new SecretKeySpec(key, "AES");
      SecretKeySpec? は、SecretKey? を継承したものだから、文法上は良いと言えば良いんだが・・・
       
    • 暗号化ライブラリのクラス構造に一貫性が無いなぁ

Java


トップ   編集 凍結解除 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS   sitemap
Last-modified: 2007-05-13 (日) 00:40:11 (3499d)
ISBN10
ISBN13
9784061426061