RSA 暗号のコード
privateKey.getEncoded().length > publicKey.getEncoded().length になるのは何でだろう.公開鍵の方が長いと思っていたのに.
rsa.java
// package packagename; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.security.InvalidKeyException; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import java.security.spec.EncodedKeySpec; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.logging.Level; import java.util.logging.Logger; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; /** * 公開鍵暗号の一種RSA暗号をJavaで実装 * http://lab.moyo.biz/recipes/java/security/publickey.xsp * -キーペア生成 * -個人鍵での復号 * -公開鍵での暗号化 * -鍵のファイル入出力機能 * @author Guernsey */ public class Rsa { private static final String CRYPT_ALGORITHM = "RSA"; public static void main(String[] args) { // キーペア生成 KeyPair keyPair = genKeyPair(); // 個人鍵と公開鍵を取得 PrivateKey privateKey = keyPair.getPrivate(); PublicKey publicKey = keyPair.getPublic(); // 使用するキーペア System.out.println("個人鍵"); System.out.println(byte2String(privateKey.getEncoded())); System.out.println("公開鍵"); System.out.println(byte2String(publicKey.getEncoded())); // 暗号化したいデータをバイト列で用意 String string = "暗号化したい.abcabc123123!!"; byte[] src = string.getBytes(); System.out.println("暗号化するデータ(String)"); System.out.println(string); System.out.println("暗号化するデータ(byte)"); System.out.println(byte2String(src)); // 暗号化 byte[] enc = encrypt(src, publicKey); System.out.println("暗号化後データ"); System.out.println(byte2String(enc)); // 復号 byte[] dec = decrypt(enc, privateKey); System.out.println("復号後データ"); System.out.println(byte2String(dec)); } private static String byte2String(byte[] b){ // ハッシュを16進数文字列に変換 StringBuffer sb= new StringBuffer(); int cnt= b.length; for(int i= 0; i< cnt; i++){ sb.append(Integer.toHexString( (b[i]>> 4) & 0x0F ) ); sb.append(Integer.toHexString( b[i] & 0x0F ) ); } return sb.toString(); } /** * バイナリを公開鍵で復号 * @param source 復号したいバイト列 * @param privateKey * @return 復号したバイト列.失敗時は null */ public static byte[] decrypt(byte[] source, PrivateKey privateKey){ try { Cipher cipher = Cipher.getInstance(getCRYPT_ALGORITHM()); cipher.init(Cipher.DECRYPT_MODE, privateKey); return cipher.doFinal(source); } catch (IllegalBlockSizeException ex) { Logger.getLogger(Rsa.class.getName()).log(Level.SEVERE, null, ex); } catch (BadPaddingException ex) { Logger.getLogger(Rsa.class.getName()).log(Level.SEVERE, null, ex); } catch (InvalidKeyException ex) { Logger.getLogger(Rsa.class.getName()).log(Level.SEVERE, null, ex); } catch (NoSuchAlgorithmException ex) { Logger.getLogger(Rsa.class.getName()).log(Level.SEVERE, null, ex); } catch (NoSuchPaddingException ex) { Logger.getLogger(Rsa.class.getName()).log(Level.SEVERE, null, ex); } return null; } /** * バイナリを秘密鍵で暗号化 * @param source 暗号化したいバイト列 * @param publicKey * @return 暗号化したバイト列.失敗時は null */ public static byte[] encrypt(byte[] source, PublicKey publicKey){ try { Cipher cipher = Cipher.getInstance(getCRYPT_ALGORITHM()); cipher.init(Cipher.ENCRYPT_MODE, publicKey); return cipher.doFinal(source); } catch (IllegalBlockSizeException ex) { Logger.getLogger(Rsa.class.getName()).log(Level.SEVERE, null, ex); } catch (BadPaddingException ex) { Logger.getLogger(Rsa.class.getName()).log(Level.SEVERE, null, ex); } catch (InvalidKeyException ex) { Logger.getLogger(Rsa.class.getName()).log(Level.SEVERE, null, ex); } catch (NoSuchAlgorithmException ex) { Logger.getLogger(Rsa.class.getName()).log(Level.SEVERE, null, ex); } catch (NoSuchPaddingException ex) { Logger.getLogger(Rsa.class.getName()).log(Level.SEVERE, null, ex); } return null; } /** * 公開鍵暗号のキーペアを生成する. * 公開鍵ビット長は 1024 * getPrivate(), getPublic() で秘密鍵,公開鍵を参照できる. * @return キーペア.失敗時は null */ public static KeyPair genKeyPair(){ KeyPairGenerator generator; try { generator = KeyPairGenerator.getInstance(getCRYPT_ALGORITHM()); SecureRandom random = SecureRandom.getInstance("SHA1PRNG"); generator.initialize(1024, random); return generator.generateKeyPair(); } catch (NoSuchAlgorithmException ex) { Logger.getLogger(Rsa.class.getName()).log(Level.SEVERE, null, ex); } return null; } /** * 個人鍵を外部ファイルから読み込む * @param filename ファイル名 * @return 個人鍵.失敗時は null */ public static PrivateKey loadPrivateKey(String filename){ try { KeyFactory keyFactory = KeyFactory.getInstance(getCRYPT_ALGORITHM()); byte[] b = loadBinary(filename); EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(b); return keyFactory.generatePrivate(keySpec); } catch (InvalidKeySpecException ex) { Logger.getLogger(Rsa.class.getName()).log(Level.SEVERE, null, ex); } catch (NoSuchAlgorithmException ex) { Logger.getLogger(Rsa.class.getName()).log(Level.SEVERE, null, ex); } return null; } /** * 公開鍵を外部ファイルから読み込む * @param filename ファイル名 * @return 公開鍵.失敗時は null */ public static PublicKey loadPublicKey(String filename){ try { KeyFactory keyFactory = KeyFactory.getInstance(getCRYPT_ALGORITHM()); byte[] b = loadBinary(filename); EncodedKeySpec keySpec = new X509EncodedKeySpec(b); return keyFactory.generatePublic(keySpec); } catch (InvalidKeySpecException ex) { Logger.getLogger(Rsa.class.getName()).log(Level.SEVERE, null, ex); } catch (NoSuchAlgorithmException ex) { Logger.getLogger(Rsa.class.getName()).log(Level.SEVERE, null, ex); } return null; } /** * バイナリを外部ファイルから入力する * @param filename ファイル名 * @return 読み込んだバイト配列.失敗時は null */ private static byte[] loadBinary(String filename){ try { FileInputStream in = new FileInputStream(filename); byte[] b = null; in.read(b); return b; } catch (FileNotFoundException ex) { Logger.getLogger(Rsa.class.getName()).log(Level.SEVERE, null, ex); } catch (IOException ex) { Logger.getLogger(Rsa.class.getName()).log(Level.SEVERE, null, ex); } return null; } /** * 個人鍵を外部ファイルに保存する * @param privateKey * @param filename ファイル名 */ public static void savePrivateKey(PrivateKey privateKey, String filename){ saveBinary(privateKey.getEncoded(), filename); } /** * 公開鍵を外部ファイルに保存する * @param publicKey * @param filename ファイル名 */ public static void savePublickkey(PublicKey publicKey, String filename) { saveBinary(publicKey.getEncoded(), filename); } /** * バイナリを外部ファイルに保存する * @param b 保存したいバイト配列 * @param filename ファイル名 */ private static void saveBinary(byte[] b, String filename) { FileOutputStream out; try { out = new FileOutputStream(filename); out.write(b); out.close(); } catch (FileNotFoundException ex) { Logger.getLogger(Rsa.class.getName()).log(Level.SEVERE, null, ex); } catch (IOException ex) { Logger.getLogger(Rsa.class.getName()).log(Level.SEVERE, null, ex); } } /** * @return the CRYPT_ALGORITHM */ public static String getCRYPT_ALGORITHM() { return CRYPT_ALGORITHM; } }
クラス実行例
run: 個人鍵 30820276020100300d06092a864886f70d0101010500048202603082025c020100028181008c0d21c5de7898e72f7e790e333d9139a69d68a9499531a42ebf0eb6845511b7f170744b2a30a3f189a3a5c8ac7e0cec4d00c73a24e09ce5843e91c82bdb2a6c64d25e625e9d94926ba889f717e3cb17f53dd69f2d1f1c71eced55f5ecb8c488025313ba064281e93028e1a3e672ff3bbf4828a6280430180e07db94b70aa66702030100010281804693fb981ed441a20802417951834e63723ed356b4b95609fa70d8364c9c1e50c780b76a85b97b7526baecba238b6671d320784629fd73b40aa0099189e06a10f33b7b61e99bc0c25ef1cb18d06f3ae191944c6a75b7f7ba2c831d68de925d785c70d827c5c18908b9265967152c1b728dcd6d17aa6440a2fcb735a42010e189024100da43db97ca75e9e9ac3db4618beeb1ad001c072cb5701c6c745fdd700c8f537e06b07a83c0b137e93299a508362a8195375382d4a69a510f574c85f72db943ad024100a443a1148097eacabb3ef24e373a7473299be46e7d76738d6afe54512ad9d80429973315afadf666a1815b96245b3e770f826732091f6f97baa5060bdea6b4e3024100a8e294c9b0d8e833ed1899b858e44b0ac7e8e80c4a20037e4fd5d5abdbac133892c87f23ef37b14179ebb4ecd3acb433d76980f4362d75c75f0f51215f79d8c902404c72e133ee89458fe6c76bf3f506328e2a6e5049100121d44e58619b890aebdb3c140f856746da67778101c405d5a563ba0721ca0aaee3bbc4f4eab4798232ab02405e76bc60582f9bf041302323bdab7ed9cef1b19f59dff49263ce77558122c5c404e8532389987d3aa12ab88d6a2492cee18ef8227b105c735fd86fe38d851390 公開鍵 30819f300d06092a864886f70d010101050003818d00308189028181008c0d21c5de7898e72f7e790e333d9139a69d68a9499531a42ebf0eb6845511b7f170744b2a30a3f189a3a5c8ac7e0cec4d00c73a24e09ce5843e91c82bdb2a6c64d25e625e9d94926ba889f717e3cb17f53dd69f2d1f1c71eced55f5ecb8c488025313ba064281e93028e1a3e672ff3bbf4828a6280430180e07db94b70aa6670203010001 暗号化するコード(String) 暗号化したい.abcabc123123!! 暗号化するコード(byte) 88c38d8689bb82b582bd82a281446162636162633132333132332121 暗号化後データ 521c0da61efce5f181896a6481edc85d1b96ea605ccff48cd7f23004a36454ac0824e5999c417bbbacd740cee33d50e64b6afb4f62b5067acbde8aefb36727f13dff81d220d7a83dc9c5f7c88468db6758bde6e6d258acf3e44b3bc6f499e81855a99d57f84b24e671c568e03fa2ce2dd5beb3b55907d8960e135307317ae49e 復号後データ 88c38d8689bb82b582bd82a281446162636162633132333132332121 構築成功 (合計時間: 2 秒)