Java语言实现区块链(四)

一、签名和校验

比特币通过对交易进行签名和校验,保证交易的安全性。

下图展示了数据签名和交易的过程。

签名过程:

1)使用哈希算法对数据文件进行加密处理,得到一个哈希值;

2)使用私钥对哈希值进行加密,生成数字签名;

3)最后把数据文件和数字签名一起发送给对方;

 

校验过程:

1)对方接收到数据文件和数字签名之后,首先使用相同的哈希算法对数据文件进行加密处理,得到一个哈希值;

2)使用公钥对数字签名进行解密,得到解密后的哈希;

3)将1和2得到的哈希值进行比较,如果相等代表验证通过;

 

二、添加交易功能

(1)定义和初始化钱包

// 钱包
public class Wallet {// 钱包私钥public PrivateKey privateKey;// 钱包公钥public PublicKey publicKey;// 用户名字,创建钱包时候传入private String name;public Wallet(String name) {this.name = name;// 判断私钥和公钥是否存在,如果不存在,则创建它们File priKeyFile = new File(name + ".pri");File pubKeyFile = new File(name + ".pub");if (!priKeyFile.exists() || priKeyFile.length() == 0|| !pubKeyFile.exists() || pubKeyFile.length() == 0) {RSAUtils.generateKeysJS("RSA", name + ".pri", name + ".pub");}}
}

(2)定义交易

// 交易
public class Transaction {// 付款方公钥public String senderPublicKey;// 收款方公钥public String receiverPublicKey;// 金额public String content;// 签名public String signaturedData;public Transaction() {}public Transaction(String senderPublicKey, String receiverPublicKey, String content, String signaturedData) {this.senderPublicKey = senderPublicKey;this.receiverPublicKey = receiverPublicKey;this.content = content;this.signaturedData = signaturedData;}...
}

(3)在Wallet中提供创建交易的方法。 

// 转账
// 参数一:接收方的公钥
// 参数二:交易数据
public Transaction sendMoney(String receiverPublicKey, String content) {// 生成签名String signature = RSAUtils.getSignature("SHA256withRSA", privateKey, content);// 把publicKey对象转换成字符串String senderPublicKey = Base64.encode(publicKey.getEncoded());// 创建并返回交易return new Transaction(senderPublicKey, receiverPublicKey, content, signature);
}

(4)在Transaction中定义校验交易的方法。

// 校验交易的方法
public boolean verify() {PublicKey publicKey = RSAUtils.getPublicKeyFromString("RSA", senderPublicKey);return RSAUtils.verifyDataJS("SHA256withRSA", publicKey, content, signaturedData);
}

(5)在客户端生成私钥。

第一步:添加发送方的私钥和公钥(数字签名和认证),以及接收方公钥(对方钱包地址)的输入框;

注意:赋值内容到textarea输入框时候,标签之间不要有空格和换行。因为空格和换行都要导致哈希运算的结果不正确。

第二步:修改addBlock方法,在该方法中生成私钥,并发送给后台处理。

// 创建普通区块
function addBlock() {// 发送方私钥var senderPrivateKey = $("#senderPrivateKey").val();// 发送方公钥var senderPublicKey = $("#senderPublicKey").val();// 接收方公钥var receiverPublicKey = $("#receiverPublicKey").val();// 获取用户输入的内容var content = $("#content").val();//-------------------- 生成签名信息 -----------------// 获取私钥var prvKey = KEYUTIL.getKey(senderPrivateKey);// 指定算法var sig = new KJUR.crypto.Signature({"alg": "SHA256withRSA"});// 初始化私钥sig.init(prvKey);// 传入原文sig.updateString(content)// 生成签名var sigValueHex = sig.sign()console.log(sigValueHex);//----------------------------------------------------// 显示进度条loading.baosight.showPageLoadingMsg(false);// 发起请求$.post("addBlock", {senderPublicKey: senderPublicKey,receiverPublicKey: receiverPublicKey,content: content,signaturedData: sigValueHex}, function(data) {// 展示操作结果$("#result").html(data)// 展示最新数据showList();// 清空输入框$("#content").val("");// 隐藏进度条loading.baosight.hidePageLoadingMsg();});
}

(6)修改BlockController的addBlock方法,把方法参数改为Transaction对象,并且添加签名校验。

@RequestMapping(value = "/addBlock", method = RequestMethod.POST)
//public String addBlock(String content) {
public String addBlock(Transaction tx) {try {//noteBook.addBlock(content);//System.out.println(tx);if (tx.verify()) {// 把Transaction对象转换成字符串ObjectMapper objectMapper = new ObjectMapper();String txInfo = objectMapper.writeValueAsString(tx);// 执行添加操作noteBook.addBlock(txInfo);return "添加区块成功!";} else {throw new RuntimeException("交易数据校验失败!");}} catch (Exception e) {return "添加失败:" + e.getMessage();}
}

 


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部