Java - пример цифровых подписей
ВAsymmetric Cryptography example мы обсуждали использование пары открытых ключей в криптографии. Another important use of the Public Key Infrastructure is in Digital Signatures. Digital Signatures are the digital equivalent of handwritten signatures with one important difference; they are not unique but come as a product of the message.
Действительная цифровая подпись дает получателю основание полагать, что сообщение было создано известным отправителем (authentication), что отправитель не может отрицать отправку сообщения (non-repudiation) и что сообщение не было изменено в пути (integrity). (Источник:Wikipedia)
1. Создание пары открытого и закрытого ключей
Код для создания пары открытый-закрытый ключ идентичен тому, который используется вAsymmetric
Cryptography example, обратитесь к шагу 1 или загрузите исходный код в конце статьи, который включает все источники -GenerateKeys.java

2. Подпишите сообщение
Затем мы должны написать наше сообщение и подписать его. Сообщение и подпись могут быть отдельными файлами, но в нашем примере мы добавляем их вList изbyte[] и записываем их как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 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();
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. Проверить подпись
У получателя есть файл(he knows it is a List of 2
byte arrays; the message and the signature), и он хочет проверить, что сообщение пришло из ожидаемого источника с предварительно предоставленным открытым ключом.
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 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) 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 ---------------- Hello from example.com!!
Скачать исходный код
Скачать -digitalsignatures.zip (6 КБ)