Java – デジタル署名の例
非対称暗号化の例
では、暗号化における公開鍵ペアの使用について説明しました。公開鍵インフラストラクチャのもう1つの重要な用途は、デジタル署名です。デジタル署名は、1つの重要な違いを持つ手書き署名のデジタル同等物です。彼らは一意ではなく、メッセージの産物として来ます。
A valid digital signature gives a recipient reason to believe that the
message was created by a known sender (
authentication
), that the
sender cannot deny having sent the message (
non-repudiation
), and that
the message was not altered in transit (
integrity
). (Source:
Wikipedia
)
1.公開鍵と秘密鍵のペアを生成する
公開鍵と秘密鍵のペアを生成するコードは、
Asymmetric Cryptographyの例
で使用されているものと同じですが、手順1を参照するか、すべてのソースを含む記事 –
GenerateKeys.java
2.メッセージに署名する
次にメッセージを書いて署名しなければなりません。メッセージとシグネチャは別々のファイルにすることができますが、この例では、それらを
byte[]`の `List`に追加し、
Object`としてファイルに書き込みます。
Message.java
package com.techfou.sender; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; import java.nio.file.Files; import java.security.InvalidKeyException; import java.security.KeyFactory; import java.security.PrivateKey; import java.security.Signature; import java.security.spec.PKCS8EncodedKeySpec; import java.util.ArrayList; import java.util.List; import javax.swing.JOptionPane; public class Message { private List<byte[]> list; //The constructor of Message class builds the list that will be written to the file. //The list consists of the message and the signature. public Message(String data, String keyFile) throws InvalidKeyException, Exception { list = new ArrayList<byte[]>(); list.add(data.getBytes()); list.add(sign(data, keyFile)); } //The method that signs the data using the private key that is stored in keyFile path public byte[]sign(String data, String keyFile) throws InvalidKeyException, Exception{ Signature rsa = Signature.getInstance("SHA1withRSA"); rsa.initSign(getPrivate(keyFile)); rsa.update(data.getBytes()); return rsa.sign(); } //Method to retrieve the Private Key from a file public PrivateKey getPrivate(String filename) throws Exception { byte[]keyBytes = Files.readAllBytes(new File(filename).toPath()); PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory kf = KeyFactory.getInstance("RSA"); return kf.generatePrivate(spec); } //Method to write the List of byte[]to a file private void writeToFile(String filename) throws FileNotFoundException, IOException { File f = new File(filename); f.getParentFile().mkdirs(); ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(filename)); out.writeObject(list); out.close(); System.out.println("Your file is ready."); } public static void main(String[]args) throws InvalidKeyException, IOException, Exception{ String data = JOptionPane.showInputDialog("Type your message here"); new Message(data, "MyKeys/privateKey").writeToFile("MyData/SignedData.txt"); } }
出力:
Your file is ready.
3.署名を確認する
受信者はファイル
(彼はそれが2バイト配列の `リスト`であることを知っています;メッセージと署名)
があり、そのメッセージが事前共有された公開鍵で期待されるソースから来たものであることを検証したい。
VerifyMessage.java
package com.techfou.receiver; import java.io.File; import java.io.FileInputStream; import java.io.ObjectInputStream; import java.nio.file.Files; import java.security.KeyFactory; import java.security.PublicKey; import java.security.Signature; import java.security.spec.X509EncodedKeySpec; import java.util.List; public class VerifyMessage { private List<byte[]> list; @SuppressWarnings("unchecked") //The constructor of VerifyMessage class retrieves the byte arrays from the File //and prints the message only if the signature is verified. public VerifyMessage(String filename, String keyFile) throws Exception { ObjectInputStream in = new ObjectInputStream(new FileInputStream(filename)); this.list = (List<byte[]>) in.readObject(); in.close(); System.out.println(verifySignature(list.get(0), list.get(1), keyFile) ? "VERIFIED MESSAGE" + "\n----------------\n" + new String(list.get(0)) : "Could not verify the signature."); } //Method for signature verification that initializes with the Public Key, //updates the data to be verified and then verifies them using the signature private boolean verifySignature(byte[]data, byte[]signature, String keyFile) throws Exception { Signature sig = Signature.getInstance("SHA1withRSA"); sig.initVerify(getPublic(keyFile)); sig.update(data); return sig.verify(signature); } //Method to retrieve the Public Key from a file public PublicKey getPublic(String filename) throws Exception { byte[]keyBytes = Files.readAllBytes(new File(filename).toPath()); X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes); KeyFactory kf = KeyFactory.getInstance("RSA"); return kf.generatePublic(spec); } public static void main(String[]args) throws Exception{ new VerifyMessage("MyData/SignedData.txt", "MyKeys/publicKey"); } }
出力:
VERIFIED MESSAGE ---------------- こんにちはmkyong.comから!
Download Source Code
Download –
digitalsignatures.zip
(6 KB)