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));
}
}
利用できる暗号アルゴリズム †
- 暗号アルゴリズム
DES | Data Encryption Standard。鍵長は64bit (8bit毎に1bitのパリティが付くので実質56bit) |
DESEde | DESを3回施す暗号方式。鍵長は192bit |
AES | Advanced Encryption Standard。鍵長は128bit、192bit、256bit |
- Block Mode
NONE | なし |
CBC | FIPS PUB 81。Cipher Block Chaining Mode |
CFB | FIPS PUB 81。Cipher Feedback Mode |
ECB | FIPS PUB 81。Electronic Codebook Mode。米国商務省標準「DES Modes of Operation」 |
OFB | FIPS PUB 81。Output Feedback Mode |
PCBC | Kerberos Version 4。Propagating Cipher Block Chaining |
- Padding Mode
NoPadding? | なし |
ISO10126Padding | W3C形式 |
OAEPWith<digest>And<mgf>Padding | PKCS #1 |
PKCS5Padding | PKCS #5 |
SSL3Padding | SSL Protocol Version 3.0 |
AES暗号の実装について †
- 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)
- キーの作り方が 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