ここでは,Java APIで標準技術を使ったセキュリティについて 述べます.1つは,署名を用いた認証技術, もう1つは,ポリシーファイルとPermissionを用いたアクセス制御です. また,これらに必要なツール,keytool,jarsigner,policytoolの 3つを紹介します. |
暗号・復号,認証 |
他人には知られたくないデータをやりとりする場合があります.
これらをネットワーク上でデータのやりとりを実施するとき,
そのデータは,ネットワーク上で意味がないデータにする必要があります.
それが暗号・復号技術です.
また,他人から送られてきたデータが誰から送られてきたものかを
知るための技術が認証です.
この認証技術は暗号,復号技術を応用して行われます.
暗号・復号の種類として,3種類あります.
暗号化する鍵と復号化する鍵が同じであるという特徴を持ちます. ただし,鍵をあらかじめ配布しておかなくてはいけないことや 鍵の管理が煩雑になるといった問題点もあります. 暗号化する鍵と復号化する鍵が異なります. 2つの鍵のうち,片方を公開(公開鍵)し, もう片方を秘密(秘密鍵)にします. 片方の鍵で暗号化すると, そのデータはもう片方の鍵でしか復号できません. しかし,実行速度が遅いと行った問題点があります. 上記の2つの特徴を生かした方式です. まず,共通鍵を公開鍵暗号方式で交換し, その後のデータのやりとりを共通鍵暗号方式で 行います.
Bの公開鍵で暗号化する. つまり,そのデータはBの秘密鍵しか復号化できない. したがって,Bしか閲覧できない. Aの秘密鍵で暗号化する. Aの公開鍵で復号化できるものは,Aしかつくれない. つまり,Aがこのデータを送ってきたことになる. |
公開鍵による署名の生成,検証 |
まずは,公開鍵,秘密鍵のペアを作成する方法です.
今回は,DSA暗号,SHA1PRNG乱数を用います.
import java.security.*; public class SigTest{ public static void main(String[] args){ //データの設定 byte[] data = "Hello".getBytes(); if(args.length > 0){ data = args[0].getBytes(); } //DHAという公開鍵暗号方式を生成するKeyPairGeneratorを作成 KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA"); //SHA1PRNGという乱数を生成するSecureRandomを作成 SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN"); //現在時刻で乱数を初期化 random.setSeed(System.currentTimeMillis()); //Generatorを乱数で初期化し,1024bitの鍵生成に設定 keyGen.initialize(1024, random); //KeyPairGeneratorからKeyPairを作成 KeyPair pair = keyGen.generateKeyPair(); //SHA1withDSAという署名方式を利用 Signature dsa = Signature.getInstance("SHA1withDSA"); //KeyPairから秘密鍵(PrivateKey)を獲得 PrivateKey priv = pair.getPrivate(); //Signatureを獲得した秘密鍵で初期化 dsa.initSign(priv); //Signatureに署名したいデータを入力 dsa.update(data); //署名を獲得 byte[] sig = dsa.sign(); //KeyPairから公開鍵(PubicKey)を獲得 PublicKey pub = pair.getPublic(); //公開鍵でSignatureを初期化 dsa.initVerify(pub); //Signatureに検証したいデータを入力 dsa.update(data); //Signatureに対して,署名を入力し検証 boolean verifies = dsa.verify(sig); //成功するとtrue,失敗するとfalse System.out.println("signature verifies: " + verifies); } }本来であれば,同じところで署名作成&検証を行うことは おかしなことです.ここでは,署名の作成法と署名の検証法を 覚えてもらえばよいです. 本来の姿である署名作成と署名検証の分離には, 以下で述べるkeytoolを用いる必要があります. |
メッセージダイジェスト |
先ほどは,データ全体に対して署名を施しました.
しかし,データが大きくなってしまうと,
それだけ処理時間がかかってしまいます.
そこで,データの要約を生成するメッセージダイジェストを
用いる方法があります.
メッセージダイジェストとは,一方向関数なので,
メッセージダイジェストからもともとのデータはわかりません.
また,異なるデータから作成されるメッセージダイジェストは
必ず違うという特徴があります.
それでは,メッセージダイジェストを作成する例をだします. 今回は,SHAをメッセージダイジェストのアルゴリズムとして用います. public class MDTest{ public static void main(String[] args){ byte[] data = "Hello".getByte(); if(args.length > 0){ data = args[0].getByte(); } //SHAのMessageDigestを作成 MessageDigest md = MessageDigest.getInstance("SHA"); //与えられたデータでMessageDigestを更新 md.update(data); //MessageDigestからダイジェスト値を獲得 byte[] digest = md.digest(); //ダイジェスト値の出力 for(int i = 0; i < digest.length; i++){ System.out.print(digest[i]); } System.out.println(""); }実際の流れとしては,以下のようになります.
|
ツールの紹介(keytool, jarsigner, policytool) |
Javaで鍵の作成やクラスファイルに証明書をつけたりするために,
ツールを利用します.
|
独自のPermissionを作る |
FilePermission等のあらかじめ与えられたPermissionではなく,
自分で独自のpermissionを作成する方法を簡単に述べます.
Permissionを独自で作成する時に注意することは以下の通りです.
|
SecurityManager関連 |
独自Permissionをチェックするためには,以下のコードをチェックしたい
ところで,挿入します.
try{ //Permissionの作成 Permission p = new Permission(String name, String action); //Permissionのチェック AccessController.checkPermission(Permision p); }catch(SecurityException ex){ System.err.println(ex); }Permissionをチェックするときは, checkPermissionを呼び出したクラスだけでなく, そのクラスの呼び出し先のクラスまで, クラスがPermissionを保持しているかどうかをチェックします. チェックに失敗すると,SecurityExceptionをthrowします. |