Java 数字签名的例子

摘要: 用数字签名的作用,主要是用来确保消息的正确性,确实是双方都是可靠的,以前介绍过RSA 加解密,那么在做数据签名的时候,一样会用到RSA算法,这是非对称加解密。在用java 开发应用的时候,对安全性比较的高的交互,都需要签名,特别是有金钱往来的时候, 这里做了一个简单的例子,用JAVA 来实现数据的签名。

用数字签名的作用,主要是用来确保消息的正确性,确实是双方都是可靠的,以前介绍过RSA 加解密,那么在做数据签名的时候,一样会用到RSA算法,这是非对称加解密。

在用java 开发应用的时候,对安全性比较的高的交互,都需要签名,特别是有金钱往来的时候, 这里做了一个简单的例子,用JAVA 来实现数据的签名。



1. 第一步,生成公钥私钥,用的RSA,非对称加解密:

package com.yihaomen.keypair;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;

public class GenerateKeys {

    private KeyPairGenerator keyGen;
    private KeyPair pair;
    private PrivateKey privateKey;
    private PublicKey publicKey;

    public GenerateKeys(int keylength) throws NoSuchAlgorithmException, NoSuchProviderException {

        this.keyGen = KeyPairGenerator.getInstance("RSA");
        this.keyGen.initialize(keylength);
    }

    public void createKeys() {
        this.pair = this.keyGen.generateKeyPair();
        this.privateKey = pair.getPrivate();
        this.publicKey = pair.getPublic();

    }

    public PrivateKey getPrivateKey() {
        return this.privateKey;
    }

    public PublicKey getPublicKey() {
        return this.publicKey;
    }

    public void writeToFile(String path, byte[] key) throws IOException {

        File f = new File(path);
        f.getParentFile().mkdirs();

        FileOutputStream fos = new FileOutputStream(f);
        fos.write(key);
        fos.flush();
        fos.close();

    }

    public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
        GenerateKeys myKeys = new GenerateKeys(1024);
        myKeys.createKeys();
        myKeys.writeToFile("MyKeys/publicKey", myKeys.getPublicKey().getEncoded());
        myKeys.writeToFile("MyKeys/privateKey", myKeys.getPrivateKey().getEncoded());
    }
}


2. 用生成的公钥加密我们要的数据:
package com.yihaomen.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 dsa = Signature.getInstance("SHA1withRSA"); 
		dsa.initSign(getPrivate(keyFile));
		dsa.update(data.getBytes());
		return dsa.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");
	}
}



3. 接收方验证数据是否正确, 也就是私钥解密
package com.yihaomen.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");
	}
}



最后,奉上源代码下载:
java digit signature sample download

上一篇: virtual box 报错: 内存不能written的解决办法
下一篇: VirtualBox 在虚拟机和主机之间拷贝文件设置
 评论 ( What Do You Think )
名称
邮箱
网址
评论
验证
   
 

 


  • 微信公众号

  • 我的微信

站点声明:

1、一号门博客CMS,由Python, MySQL, Nginx, Wsgi 强力驱动

2、部分文章或者资源来源于互联网, 有时候很难判断是否侵权, 若有侵权, 请联系邮箱:summer@yihaomen.com, 同时欢迎大家注册用户,主动发布无版权争议的 文章/资源.

3、鄂ICP备14001754号-3, 鄂公网安备 42280202422812号