提交 1edb9241 编写于 作者: G guop 提交者: ninecents

添加RSA签名验签功能 #84

1. 签名验签库使用了jsrsasign作为算法库
2. 添加了签名验签页面路由和相关配置文件
上级 9bbfa50d
此差异已折叠。
...@@ -34,6 +34,7 @@ const tool = [ ...@@ -34,6 +34,7 @@ const tool = [
'title': '加密/解密', 'title': '加密/解密',
'cat': ['encryption'] 'cat': ['encryption']
}, },
{'name': 'sign', 'title': '签名/验签', 'cat': ['encryption']},
{'name': 'base64', 'title': 'BASE64编码', 'cat': ['encryption']}, {'name': 'base64', 'title': 'BASE64编码', 'cat': ['encryption']},
{'name': 'json', 'title': 'JSON工具', 'cat': ['conversion', 'serialize']}, {'name': 'json', 'title': 'JSON工具', 'cat': ['conversion', 'serialize']},
{'name': 'url', 'title': 'URL编码', 'cat': ['conversion']}, {'name': 'url', 'title': 'URL编码', 'cat': ['conversion']},
......
...@@ -46,6 +46,10 @@ const routes = [ ...@@ -46,6 +46,10 @@ const routes = [
path: '/tool/encrypt', path: '/tool/encrypt',
component: r => require(['./views/tool/encrypt.vue'], r) component: r => require(['./views/tool/encrypt.vue'], r)
}, },
{
path: '/tool/sign',
component: r => require(['./views/tool/sign.vue'], r)
},
{ {
path: '/tool/hash', path: '/tool/hash',
component: r => require(['./views/tool/hash.vue'], r) component: r => require(['./views/tool/hash.vue'], r)
......
<template> <template>
<div> <div>
<heightResize :append="['.page-option-block']" ignore @resize="resize"> <Input v-model="current.signData" :rows="7" type="textarea" placeholder="待签名内容/验签数据"></Input>
<Row :gutter="10"> <Input v-model="current.privateKey" :rows="7" type="textarea" placeholder="PEM格式私钥"></Input>
<Col span="12"> <option-block>
<input-block top="5px" type="default" :text="$t('sign_sign_data')" @on-default-right-bottom-click="()=>copy('signData')"> <FormItem>
<autoHeightTextarea :height="height1" v-model="current.signData"></autoHeightTextarea> <Select v-model="current.algorithm" style="width: 200px">
</input-block> <Option v-for="v in algorithm" :value="v" :key="v">{{ v }}</Option>
</Col> </Select>
<Col span="12"> </FormItem>
<input-block top="5px" type="default" :text="$t('sign_verify_code')" @on-default-right-bottom-click="()=>copy('verifyCode')"> <FormItem>
<autoHeightTextarea :height="height1" v-model="current.verifyCode"></autoHeightTextarea> <ButtonGroup>
</input-block> <Button type="primary" @click="sign()">签名</Button>
</Col> <Button type="primary" @click="verify()">验签</Button>
</Row> </ButtonGroup>
<option-block class="page-option-block" center>
<FormItem> </FormItem>
<Select v-model="current.algorithm" style="width: 200px"> </option-block>
<Option v-for="v in algorithm" :value="v" :key="v">{{ v }}</Option> <Input v-model="current.publicKey" :rows="7" type="textarea" placeholder="PEM格式公钥"></Input>
</Select> <Input v-model="current.verifyCode" :rows="7" type="textarea" placeholder="Base64编码后签名"></Input>
</FormItem> </div>
<FormItem>
<ButtonGroup>
<Button type="primary" @click="sign()">{{ $t('sign_sign') }}</Button>
<Button type="primary" @click="verify()">{{ $t('sign_verify') }}</Button>
</ButtonGroup>
</FormItem>
<FormItem>
<Button type="default" @click="openGenerateKeypairBlock()">{{ $t('sign_generate_keypair') }}</Button>
</FormItem>
</option-block>
<Row :gutter="10">
<Col span="12">
<input-block top="5px" type="default" :text="$t('sign_public_key')" @on-default-right-bottom-click="()=>copy('publicKey')">
<autoHeightTextarea :height="height2" v-model="current.publicKey"></autoHeightTextarea>
</input-block>
</Col>
<Col span="12">
<input-block top="5px" type="default" :text="$t('sign_private_key')" @on-default-right-bottom-click="()=>copy('privateKey')">
<autoHeightTextarea :height="height2" v-model="current.privateKey"></autoHeightTextarea>
</input-block>
</Col>
</Row>
</heightResize>
<Modal v-model="generateKeypairData.show" :title="$t('sign_generate_keypair')">
<Form :label-width="80">
<FormItem :label="$t('sign_keypair_type')">
<Select v-model="generateKeypairData.type">
<Option value="PKCS8PRV">PKCS#8</Option>
<Option value="PKCS1PRV">PKCS#1</Option>
</Select>
</FormItem>
<FormItem :label="$t('sign_keypair_length')">
<Select v-model="generateKeypairData.length">
<Option :value="512">512 bit</Option>
<Option :value="1024">1024 bit</Option>
<Option :value="2048">2048 bit</Option>
<Option :value="4096">4096 bit</Option>
</Select>
</FormItem>
</Form>
<div slot="footer">
<Button type="text" @click="generateKeypairData.show = false">{{ $t('sign_generate_cancel') }}</Button>
<Button type="primary" disabled v-if="generateKeypairData.loading">{{ $t('sign_generate_in') }}</Button>
<Button v-else type="primary" @click="generateKeypair()">{{ $t('sign_generate') }}</Button>
</div>
</Modal>
</div>
</template> </template>
<script> <script>
import rs from "jsrsasign"; import rs from "jsrsasign";
import autoHeightTextarea from "./components/autoHeightTextarea";
import heightResize from "./components/heightResize";
export default { export default {
components:{ created() {
autoHeightTextarea, this.current = Object.assign(this.current, this.$getToolData('input'))
heightResize },
}, methods: {
created() { sign() {
this.$initToolData() let rs = require('jsrsasign')
}, if (this.current.signData && this.current.privateKey) {
methods: { let rsaPrivateKey
sign() { try {
try { rsaPrivateKey = rs.KEYUTIL.getKey(this.current.privateKey)
if (!this.current.signData || !this.current.privateKey){ } catch (e) {
throw new Error(this.$t('sign_error_sign_content_empty').toString()) this.$Message.error("无效私钥"+e)
} }
let rsaPrivateKey = rs.KEYUTIL.getKey(this.current.privateKey) let sign
let sign = new rs.KJUR.crypto.Signature({alg: this.current.algorithm}) try {
sign.init(rsaPrivateKey) sign = new rs.KJUR.crypto.Signature({alg: this.current.algorithm})
sign.updateString(this.current.signData) } catch (e) {
let signResult = sign.sign() this.$Message.error("无效签名算法")
// 转为base64 }
this.current.verifyCode = rs.hex2b64(signResult) sign.init(rsaPrivateKey)
// 自动复制签名结果到剪切板 sign.updateString(this.current.signData)
this.$clipboardCopy(this.current.verifyCode); let signResult
// 保存历史记录 try {
this.$saveToolData(this.current); signResult = sign.sign()
}catch (e){ } catch (e) {
this.$Message.error(this.$t('sign_error',[e.message]).toString()) this.$Message.error("签名时出现异常" + e)
}
},
verify() {
try {
if (!this.current.verifyCode || !this.current.publicKey){
throw new Error(this.$t('sign_error_verify_content_empty').toString())
}
let rsaPublicKey = rs.KEYUTIL.getKey(this.current.publicKey)
let sign = new rs.KJUR.crypto.Signature({alg: this.current.algorithm})
sign.init(rsaPublicKey)
sign.updateString(this.current.signData)
let hexData = rs.b64tohex(this.current.verifyCode)
let verifyResult = sign.verify(hexData)
if (!verifyResult) {
throw new Error(this.$t('sign_verify_fail').toString())
}
// 保存历史记录
this.$saveToolData(this.current);
this.$Message.info(this.$t('sign_verify_ok').toString())
}catch (e){
this.$Message.error(this.$t('sign_error',[e.message]).toString())
}
},
generateKeypair() {
this.generateKeypairData.loading = true;
setTimeout(() => {
try {
const rsaKeypair = rs.KEYUTIL.generateKeypair("RSA", this.generateKeypairData.length);
this.current.privateKey = rs.KEYUTIL.getPEM(rsaKeypair.prvKeyObj, this.generateKeypairData.type)
this.current.publicKey = rs.KEYUTIL.getPEM(rsaKeypair.pubKeyObj)
this.generateKeypairData.show = false
} catch (e) {
this.$Message.error(this.$t('sign_error',[e.message]).toString())
}
this.generateKeypairData.loading = false;
}, 500)
},
openGenerateKeypairBlock() {
this.generateKeypairData.show = true;
this.generateKeypairData.loading = false;
this.generateKeypairData.type = "PKCS8PRV";
this.generateKeypairData.length = 2048;
},
resize(height){
this.height1 = Math.min(160,Math.ceil(height/2))
this.height2 = height - this.height1
},
copy(type){
if ((type in this.current) && this.current[type]){
this.$clipboardCopy(this.current[type],true);
}
} }
// 转为base64
this.current.verifyCode = rs.hex2b64(signResult)
// 自动复制签名结果到剪切板
this.$clipboardCopy(this.current.verifyCode);
// 保存历史记录
this.$saveToolData(this.current);
}
}, },
data() { verify() {
return { if (this.current.verifyCode && this.current.publicKey) {
current: { let rsaPublicKey
signData: '', try {
privateKey: '', rsaPublicKey = rs.KEYUTIL.getKey(this.current.publicKey)
publicKey: '', } catch (e) {
verifyCode: '', this.$Message.error("无效公钥")
algorithm: 'MD5withRSA'
},
algorithm: ["MD5withRSA", "SHA1withRSA", "SHA256withRSA", "SHA512withRSA"],
generateKeypairData: {
show: false,
loading: false,
length: 2048,
type: "PKCS8PRV",
},
height1:100,
height2:100,
} }
let sign
try {
sign = new rs.KJUR.crypto.Signature({alg: this.current.algorithm})
} catch (e) {
this.$Message.error("无效签名算法")
}
sign.init(rsaPublicKey)
sign.updateString(this.current.signData)
let hexData = rs.b64tohex(this.current.verifyCode)
let verifyResult = sign.verify(hexData)
if (verifyResult) {
this.$Message.info("验签成功")
} else {
this.$Message.error("验签失败")
}
}
}
},
data() {
return {
current: {
signData: '',
privateKey: '',
publicKey: '',
verifyCode: '',
algorithm: 'MD5withRSA'
},
algorithm: ["MD5withRSA", "SHA1withRSA", "SHA256withRSA", "SHA512withRSA"]
} }
}
} }
</script> </script>
<style scoped>
</style>
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册