提交 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')">
<autoHeightTextarea :height="height1" v-model="current.signData"></autoHeightTextarea>
</input-block>
</Col>
<Col span="12">
<input-block top="5px" type="default" :text="$t('sign_verify_code')" @on-default-right-bottom-click="()=>copy('verifyCode')">
<autoHeightTextarea :height="height1" v-model="current.verifyCode"></autoHeightTextarea>
</input-block>
</Col>
</Row>
<option-block class="page-option-block" center>
<FormItem> <FormItem>
<Select v-model="current.algorithm" style="width: 200px"> <Select v-model="current.algorithm" style="width: 200px">
<Option v-for="v in algorithm" :value="v" :key="v">{{ v }}</Option> <Option v-for="v in algorithm" :value="v" :key="v">{{ v }}</Option>
...@@ -21,134 +10,79 @@ ...@@ -21,134 +10,79 @@
</FormItem> </FormItem>
<FormItem> <FormItem>
<ButtonGroup> <ButtonGroup>
<Button type="primary" @click="sign()">{{ $t('sign_sign') }}</Button> <Button type="primary" @click="sign()">签名</Button>
<Button type="primary" @click="verify()">{{ $t('sign_verify') }}</Button> <Button type="primary" @click="verify()">验签</Button>
</ButtonGroup> </ButtonGroup>
</FormItem>
<FormItem>
<Button type="default" @click="openGenerateKeypairBlock()">{{ $t('sign_generate_keypair') }}</Button>
</FormItem> </FormItem>
</option-block> </option-block>
<Row :gutter="10"> <Input v-model="current.publicKey" :rows="7" type="textarea" placeholder="PEM格式公钥"></Input>
<Col span="12"> <Input v-model="current.verifyCode" :rows="7" type="textarea" placeholder="Base64编码后签名"></Input>
<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> </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:{
autoHeightTextarea,
heightResize
},
created() { created() {
this.$initToolData() this.current = Object.assign(this.current, this.$getToolData('input'))
}, },
methods: { methods: {
sign() { sign() {
let rs = require('jsrsasign')
if (this.current.signData && this.current.privateKey) {
let rsaPrivateKey
try {
rsaPrivateKey = rs.KEYUTIL.getKey(this.current.privateKey)
} catch (e) {
this.$Message.error("无效私钥"+e)
}
let sign
try { try {
if (!this.current.signData || !this.current.privateKey){ sign = new rs.KJUR.crypto.Signature({alg: this.current.algorithm})
throw new Error(this.$t('sign_error_sign_content_empty').toString()) } catch (e) {
this.$Message.error("无效签名算法")
} }
let rsaPrivateKey = rs.KEYUTIL.getKey(this.current.privateKey)
let sign = new rs.KJUR.crypto.Signature({alg: this.current.algorithm})
sign.init(rsaPrivateKey) sign.init(rsaPrivateKey)
sign.updateString(this.current.signData) sign.updateString(this.current.signData)
let signResult = sign.sign() let signResult
try {
signResult = sign.sign()
} catch (e) {
this.$Message.error("签名时出现异常" + e)
}
// 转为base64 // 转为base64
this.current.verifyCode = rs.hex2b64(signResult) this.current.verifyCode = rs.hex2b64(signResult)
// 自动复制签名结果到剪切板 // 自动复制签名结果到剪切板
this.$clipboardCopy(this.current.verifyCode); this.$clipboardCopy(this.current.verifyCode);
// 保存历史记录 // 保存历史记录
this.$saveToolData(this.current); this.$saveToolData(this.current);
}catch (e){
this.$Message.error(this.$t('sign_error',[e.message]).toString())
} }
}, },
verify() { verify() {
if (this.current.verifyCode && this.current.publicKey) {
let rsaPublicKey
try { try {
if (!this.current.verifyCode || !this.current.publicKey){ rsaPublicKey = rs.KEYUTIL.getKey(this.current.publicKey)
throw new Error(this.$t('sign_error_verify_content_empty').toString()) } catch (e) {
this.$Message.error("无效公钥")
}
let sign
try {
sign = new rs.KJUR.crypto.Signature({alg: this.current.algorithm})
} catch (e) {
this.$Message.error("无效签名算法")
} }
let rsaPublicKey = rs.KEYUTIL.getKey(this.current.publicKey)
let sign = new rs.KJUR.crypto.Signature({alg: this.current.algorithm})
sign.init(rsaPublicKey) sign.init(rsaPublicKey)
sign.updateString(this.current.signData) sign.updateString(this.current.signData)
let hexData = rs.b64tohex(this.current.verifyCode) let hexData = rs.b64tohex(this.current.verifyCode)
let verifyResult = sign.verify(hexData) let verifyResult = sign.verify(hexData)
if (!verifyResult) { if (verifyResult) {
throw new Error(this.$t('sign_verify_fail').toString()) this.$Message.info("验签成功")
} else {
this.$Message.error("验签失败")
} }
// 保存历史记录
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);
} }
} }
}, },
...@@ -161,16 +95,12 @@ export default { ...@@ -161,16 +95,12 @@ export default {
verifyCode: '', verifyCode: '',
algorithm: 'MD5withRSA' algorithm: 'MD5withRSA'
}, },
algorithm: ["MD5withRSA", "SHA1withRSA", "SHA256withRSA", "SHA512withRSA"], algorithm: ["MD5withRSA", "SHA1withRSA", "SHA256withRSA", "SHA512withRSA"]
generateKeypairData: {
show: false,
loading: false,
length: 2048,
type: "PKCS8PRV",
},
height1:100,
height2:100,
} }
} }
} }
</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.
先完成此消息的编辑!
想要评论请 注册