fullstack.web/swa/u/index.html
2024-09-19 15:25:56 +08:00

771 lines
25 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>U 盾维护工具</title>
<style>
:root {
--mainColor: salmon;
}
html, body {
margin: 0;
width: 100%;
height: 100%;
}
.title {
color: var(--mainColor);
}
.container {
margin: 2rem auto;
border: var(--mainColor) solid 2px;
border-radius: 10px;
width: 80%;
height: 80%;
min-height: 500px;
text-align: left;
}
.group {
padding: 1rem;
margin: 1rem;
}
.form input {
display: block;
margin: 0.5rem 0;
}
#btn_write_group {
display: none;
}
#mainkey_loaded {
display: none;
}
</style>
<link rel="stylesheet" type="text/css" href="tabs.css">
<link rel="stylesheet" type="text/css" href="layx.min.css">
</head>
<body>
<div style="width: 100%; text-align: center;">
<h2 class="title">信雅达 UKey 发行工具</h2>
</div>
<div class="container">
<div class="group" style="width: 100%; ">
<select id="ukeys" style="height: 1.5rem; width: 308px">
</select>
<button id="btn_refresh" style="margin-right: 1rem">&emsp;&emsp;</button>
</div>
<div class="group" style="width: 100%;">
<input id="pwd1" style="width: 300px;height: 1.06rem" type="password" maxlength="8" placeholder="口令8 个数字">
<button id="login" style="margin-right: 1rem">&emsp;&emsp;</button>
<button id="login_def" style="margin-right: 1rem">默认口令</button>
</div>
<div class="group" style="height: 10rem">
<ul class="tabs">
<li>
<a href="#" name="tab_public">UKey 发行</a>
</li>
<li>
<a href="#" name="tab_main">主密钥分散</a>
</li>
<li>
<a href="#" name="tab_main_comp">主密钥合成</a>
</li>
<li>
<a href="#" name="tab_file">文件操作</a>
</li>
<li>
<a href="#" name="tab_sign">签名</a>
</li>
<li>
<a href="#" name="tab_pin">PIN 管理</a>
</li>
<li>
<a href="#" name="tab_active">驱动程序</a>
</li>
</ul>
<div class="tabs-content">
<div class="tab tab_public" style="display: none">
<div class="form">
<input id="manufactor" style="width: 300px; height: 1.06rem" type="text" value=""
placeholder="厂家标记">
<input id="system" style="width: 300px; height: 1.06rem" type="text" value="" placeholder="系统信息">
<input id="customer" style="width: 300px; height: 1.06rem" type="text" value="" placeholder="客户信息">
</div>
<div style="margin: 1rem 0 ">
<button id="btn_nameplate_clear" style="margin-right: 1rem">清空</button>
<button id="btn_nameplate_tmp_save" style="margin-right: 1rem">临存</button>
<button id="btn_nameplate_tmp_load" style="margin-right: 1rem">临取</button>
<button id="btn_nameplate_read" style="margin-right: 1rem">返显</button>
</div>
<button id="btn_nameplate_release" style="margin-right: 1rem">&emsp;&emsp;</button>
</div>
<div class="tab tab_main" style="display: none">
<div class="form">
<button id="select_file" onclick="read()">请先载入主密钥文件</button>
<span id="mainkey_loaded">主密钥已载入,请分别写入三个 UKey</span>
</div>
<div style="margin: 3rem 0" id="btn_write_group">
<button id="btn_m1" style="margin-right: 1rem">写入分量1</button>
<button id="btn_m2" style="margin-right: 1rem">写入分量2</button>
<button id="btn_m3" style="margin-right: 1rem">写入分量3</button>
</div>
</div>
<div class="tab tab_main_comp" style="display: none">
<div style="margin: 3rem 0">
<span id="show_m1" style="display: none">[分量1已录入]</span>
<button id="btn_loadm1" style="margin-right: 1rem">读取分量1</button>
<span id="show_m2" style="display: none">[分量2已录入]</span>
<button id="btn_loadm2" style="margin-right: 1rem">写入分量2</button>
<span id="show_m3" style="display: none">[分量3已录入]</span>
<button id="btn_loadm3" style="margin-right: 1rem">写入分量3</button>
</div>
<div class="form" id="mainkey_out" style="display: none">
<p>
<span>主密钥已合成,</span><button id="mainkey_comp_show" onclick="downloadMainKey()">点我下载</button><span>!</span>
</p>
</div>
</div>
<div class="tab tab_file" style="display: none">
<input id="path" style="width: 300px; height: 1.06rem" type="text" value="\root\mana"
placeholder="文件目录">
<button id="btn_list_path" style="margin-right: 1rem">&emsp;&emsp;</button>
<textarea id="ta_files" style="display: block; margin: 1rem 0; width: 375px; height: 100px;"
readonly></textarea>
<input id="filepath" style="width: 260px; height: 1.06rem" type="text" value="\root\mana\name"
placeholder="文件">
<button id="btn_read" style="margin-right: 0.5rem"></button>
<button id="btn_write" style="margin-right: 0.5rem"></button>
<button id="btn_delete" style="margin-right: 0.5rem"></button>
<textarea id="ta_txt" style="display: block; margin: 1rem 0; width: 375px; height: 100px;"
></textarea>
</div>
<div class="tab tab_sign" style="display: none">
<textarea id="inData" style="display: block; margin: 1rem 0; width: 375px; height: 100px;" placeholder="输入签名文本"></textarea>
<button id="btn_sign" style="margin-right: 1rem">&emsp;&emsp;</button>
<textarea id="outData" style="display: block; margin: 1rem 0; width: 375px; height: 100px;" readonly></textarea>
</div>
<div class="tab tab_pin" style="display: none">
<!-- <div class="group" style="width: 100%; ">-->
<!-- <input id="pwd2" style="width: 300px;height: 1.06rem" type="password" maxlength="8"-->
<!-- placeholder="口令8 个数字">-->
<!-- <button id="login2" style="margin-right: 1rem">授&emsp;&emsp;权</button>-->
<!-- <button id="login_def2" style="margin-right: 1rem">默认口令</button>-->
<!-- </div>-->
<div class="form group">
<input id="old_pwd" style="width: 360px;height: 1.06rem" type="password" maxlength="8"
placeholder="口令8 个数字">
<input id="new_pwd1" style="width: 360px;height: 1.06rem" type="password" maxlength="8"
placeholder="新口令8 个数字">
<input id="new_pwd2" style="width: 360px;height: 1.06rem" type="password" maxlength="8"
placeholder="重复新口令8 个数字">
<button id="update1" style="margin-right: 1rem">修改操作员 PIN</button>
<button id="update2" style="margin-right: 1rem">修改管理员 PIN</button>
<button id="reset" style="margin-right: 1rem">解锁操作员 PIN</button>
</div>
</div>
<div class="tab tab_active" style="display:none; padding-top: 1rem">
<ul>
<li>
<h4 style="color: var(--mainColor);"><span>【2023年01月01日】</span> V1.0.1 <a href="./Setup_V1.0.1.exe" style="text-decoration:none; font-size: 0.5rem; font-weight: normal; cursor: pointer">(点击下载)</a> </h4>
<p>渔翁 UKey</p>
</li>
</ul>
</div>
</div>
</div>
</div>
<!-- UKey 支持, 共 3 个 js-->
<!-- jquery -->
<script type="text/javascript" src="./jquery.min.js"></script>
<script type="text/javascript" src="./fiseckey.js"></script>
<script type="text/javascript" src="./ukey.js"></script>
<script type="application/javascript" src="./gmhelper.js"></script>
<!-- 演示程序 -->
<script type="text/javascript" src="./tabs.js"></script>
<script type="application/javascript" src="layx.min.js"></script>
<script type="application/javascript" src="tools.js"></script>
<script type="application/javascript">
$(function () {
function refresh() {
var list = window.UKey.enumDevByArray()
if (list) {
var ll = list.split("|");
var options = ""
for (var i = 0; i < ll.length; i++) {
var value = ll[i].split(",")[0]
options += "<option value =\"" + value + "\">" + ll[i] + "</option>"
}
$("#ukeys").html(options);
}
}
refresh();
$("#btn_refresh").click(function () {
refresh()
success("刷新成功")
})
$("#btn_list_path").click(function () {
var path = $("#path").val();
try {
var ret = window.UKey.enumDir(path)
var out = ""
for (var i = 0; i < ret.folders.length; i++) {
out += "文件夹:\t" + ret.folders[i] + "\r\n"
}
for (var i = 0; i < ret.files.length; i++) {
out += "文件:\t" + ret.files[i] + "\r\n"
}
$("#ta_files").text(out)
success("枚举成功")
} catch (e) {
alert("枚举失败:" + e.message)
}
})
$("#login2").click(function () {
var pwd2 = $("#pwd2").val();
check(pwd2, /\d{8}/, "口令输入错误")
var ukey = $("#ukeys").val();
try {
window.UKey.admin(ukey, pwd2)
success("登录成功")
} catch (e) {
alert("登录失败:" + e.message)
}
})
$("#login_def2").click(function () {
var pwd2 = "11111111"
$("#pwd2").val(pwd2);
var ukey = $("#ukeys").val();
try {
window.UKey.admin(ukey, pwd2)
success("登录成功")
} catch (e) {
alert("登录失败:" + e.message)
}
})
$("#login").click(function () {
var pwd1 = $("#pwd1").val();
check(pwd1, /\d{8}/, "口令输入错误")
var ukey = $("#ukeys").val();
try {
window.UKey.login(ukey, pwd1)
success("登录成功")
} catch (e) {
alert("登录失败:" + e.message)
}
})
$("#login_def").click(function () {
$("#pwd1").val("12345678");
$("#login").click()
})
$("#btn_nameplate_clear").click(function () {
$("#manufactor").val("");
$("#system").val("");
$("#customer").val("");
})
$("#btn_read").click(function () {
try {
var filepath = $("#filepath").val()
var idx = filepath.lastIndexOf("\\")
var folder = filepath.substr(0, idx)
var file = filepath.substr(idx + 1)
var txt = window.UKey.readFile(folder, file);
txt = JSON.stringify(txt, null, 4)
$("#ta_txt").val( txt )
success("读取成功")
} catch (e) {
alert("读取失败:" + e.message)
}
})
$("#btn_write").click(function () {
// alert("暂不开放")
try {
var filepath = $("#filepath").val()
var idx = filepath.lastIndexOf("\\")
var folder = filepath.substr(0, idx)
var file = filepath.substr(idx + 1)
var txt = $("#ta_txt").val();
window.UKey.writeFile(folder, file, txt);
success("写入成功")
} catch (e) {
alert("写入失败:" + e.message)
}
})
$("#btn_delete").click(function () {
// alert("暂不开放")
try {
var filepath = $("#filepath").val()
var idx = filepath.lastIndexOf("\\")
var folder = filepath.substr(0, idx)
var file = filepath.substr(idx + 1)
window.UKey.deleteFile(folder, file);
success("删除成功")
} catch (e) {
alert("删除失败:" + e.message)
}
})
$("#btn_nameplate_tmp_load").click(function () {
var def = {
manufactor: "sunyard",
system: "hsm",
customer: "ICBC"
}
$("#manufactor").val(def.manufactor);
$("#system").val(def.system);
$("#customer").val(def.customer);
})
$("#btn_nameplate_read").click(function () {
try {
var txt = window.UKey.catRelease();
var def = Object.assign({
manufactor: "",
system: "",
customer: ""
}, txt)
$("#manufactor").val(def.manufactor);
$("#system").val(def.system);
$("#customer").val(def.customer);
success("返显成功")
} catch (e) {
alert("返显失败:" + e.message)
}
})
$("#btn_nameplate_tmp_load").click(function () {
var json = localStorage.getItem("tmp")
var def = {
manufactor: "sunyard",
system: "hsm",
customer: "ICBC"
}
try {
def = JSON.parse(json)
} catch (e) {
}
$("#manufactor").val(def.manufactor);
$("#system").val(def.system);
$("#customer").val(def.customer);
})
$("#btn_nameplate_tmp_save").click(function () {
var def = {
manufactor: $("#manufactor").val(),
system: $("#system").val(),
customer: $("#customer").val()
}
localStorage.setItem("tmp", JSON.stringify(def))
})
$("#btn_nameplate_release").click(function () {
var def = {
manufactor: $("#manufactor").val(),
system: $("#system").val(),
customer: $("#customer").val()
}
check(def.manufactor, /\w+/, "厂家标记填写错误")
check(def.system, /\w+/, "系统信息填写错误")
check(def.customer, /\w+/, "客户信息填写错误")
try {
window.UKey.release(def)
success("发行成功")
} catch (e) {
alert("发行失败:" + e.message)
}
})
$("#btn_sign").click(function () {
var inData = $("#inData").val()
// 公钥
var pk = window.UKey.exportPk();
var s = window.gmhelper.getHashAsBase64( inData, pk )
var outData = pk
outData += "\r\n\r\nz=" + s.z
outData += "\r\n\r\nhash=" + s.hashHex
var sign = window.UKey.sign( s.hashBase64 )
outData += "\r\n\r\nsign=" + sign
$("#outData").text(outData)
})
$("#reset").click(function () {
var ukey = $("#ukeys").val();
// 重置口令
var old_pwd = $("#old_pwd").val()
try {
window.UKey.admin(ukey, old_pwd)
success("授权成功")
} catch (e) {
alert("授权失败:" + e.message)
return
}
var new_pwd1 = $("#new_pwd1").val()
var new_pwd2 = $("#new_pwd2").val()
if ( new_pwd1 !== new_pwd2 ) {
alert("新口令两次不同")
} else {
window.UKey.updatePin(3, old_pwd, new_pwd1);
alert("执行成功")
}
})
$("#update1").click(function () {
var old_pwd = $("#old_pwd").val()
var new_pwd1 = $("#new_pwd1").val()
var new_pwd2 = $("#new_pwd2").val()
if ( new_pwd1 !== new_pwd2 ) {
alert("新口令两次不同")
} else {
window.UKey.updatePin(1, old_pwd, new_pwd1);
alert("执行成功")
}
})
$("#update2").click(function () {
var old_pwd = $("#old_pwd").val()
var new_pwd1 = $("#new_pwd1").val()
var new_pwd2 = $("#new_pwd2").val()
if ( new_pwd1 !== new_pwd2 ) {
alert("新口令两次不同")
} else {
window.UKey.updatePin(2, old_pwd, new_pwd1);
alert("执行成功")
}
})
})
</script>
<script type="application/javascript">
function read() {
var input = document.createElement('input')
input.type = 'file'
input.click() // 开始选择文件
input.onchange = () => { // 监听选择文件的结果,获取选择到的文件
var file = input.files[0]
var reader = new FileReader();
reader.onload = function(e) {
console.log(this.result);
console.log(e.target.result)
console.log(e.target.result.byteLength)
if ( ! e.target.result || 16 !== e.target.result.byteLength ) {
alert("文件格式错误")
return
}
$("#btn_write_group").show();
$("#mainkey_loaded").show();
$("#select_file").hide();
window.mk = e.target.result
}
reader.readAsArrayBuffer(file);
}
}
$("#btn_m1").click(function (){
var d = gmhelper.decentralizedMainKey(window.mk)
publicWrite('\\root\\mana\\a20', { data: '31'})
publicWrite('\\root\\mana\\a30', { data: d.m.checkValue}) // 主密钥校验值
publicWrite('\\root\\mana\\a40', { data: d.m.keyCiphertext}) // 主密钥密文
publicWrite('\\root\\mana\\a50', { data: d.p.checkValue}) // 保护密钥校验值
publicWrite('\\root\\mana\\a60', { data: d.p1}) // 保护分量1
success("写入成功")
})
$("#btn_m2").click(function (){
var d = gmhelper.decentralizedMainKey(window.mk)
publicWrite('\\root\\mana\\a20', { data: '32'})
publicWrite('\\root\\mana\\a30', { data: d.m.checkValue}) // 主密钥校验值
publicWrite('\\root\\mana\\a40', { data: d.m.keyCiphertext}) // 主密钥密文
publicWrite('\\root\\mana\\a50', { data: d.p.checkValue}) // 保护密钥校验值
publicWrite('\\root\\mana\\a60', { data: d.p2}) // 保护分量2
success("写入成功")
})
$("#btn_m3").click(function (){
var d = gmhelper.decentralizedMainKey(window.mk)
publicWrite('\\root\\mana\\a20', { data: '33'})
publicWrite('\\root\\mana\\a30', { data: d.m.checkValue}) // 主密钥校验值
publicWrite('\\root\\mana\\a40', { data: d.m.keyCiphertext}) // 主密钥密文
publicWrite('\\root\\mana\\a50', { data: d.p.checkValue}) // 保护密钥校验值
publicWrite('\\root\\mana\\a60', { data: d.p3}) // 保护分量3
success("写入成功")
})
function publicWrite(filepath, txt) {
try {
const idx = filepath.lastIndexOf("\\")
const folder = filepath.substr(0, idx)
const file = filepath.substr(idx + 1)
window.UKey.writeFile(folder, file, JSON.stringify(txt));
} catch (e) {
alert("写入失败:" + e.message)
}
}
</script>
<script type="application/javascript">
function publicRead(filepath) {
let txt = ''
try {
const idx = filepath.lastIndexOf("\\")
const folder = filepath.substr(0, idx)
const file = filepath.substr(idx + 1)
txt = window.UKey.readFile(folder, file);
return txt.data;
} catch (e) {
alert("读取失败:" + e.message)
}
return txt
}
function readKey( p ){
var role = publicRead('\\root\\mana\\a20')
console.log("role", role);
if ( role != p ) {
alert("分量编号错误")
return
}
if ( ! window.mk ) {
window.mk = {}
}
if ( 31 == p ) {
window.mk.weight0x30 = publicRead('\\root\\mana\\a30')
window.mk.weight0x40 = publicRead('\\root\\mana\\a40')
window.mk.weight0x401 = publicRead('\\root\\mana\\a40')
window.mk.weight0x50 = publicRead('\\root\\mana\\a50')
window.mk.weight0x60 = publicRead('\\root\\mana\\a60')
window.mk.weight0x601 = publicRead('\\root\\mana\\a60')
} else if ( 32 == p ) {
window.mk.weight0x402 = publicRead('\\root\\mana\\a40')
window.mk.weight0x602 = publicRead('\\root\\mana\\a60')
} else if ( 33 == p ) {
window.mk.weight0x403 = publicRead('\\root\\mana\\a40')
window.mk.weight0x603 = publicRead('\\root\\mana\\a60')
} else {
alert("分量编号错误")
}
// 每次都执行
$("#btn_loadm" + ( p - 30 )).hide()
$("#show_m" + ( p - 30 )).show()
// 全部结束后执行
if ( window.mk.weight0x601 && window.mk.weight0x602 && window.mk.weight0x603 ) {
var mk = checkValue( window.mk.weight0x601, window.mk.weight0x602, window.mk.weight0x603 )
if ( mk ) {
$("#mainkey_out").show();
window.mkd = mk;
}
}
}
$("#btn_loadm1").click(function (){
readKey( 31 )
})
$("#btn_loadm2").click(function (){
readKey( 32 )
})
$("#btn_loadm3").click(function (){
readKey( 33 )
})
// 将十六进制字符串转换为二进制数组
function hexToBytes(hex) {
const bytes = new Uint8Array(hex.length / 2);
for (let i = 0; i < hex.length; i += 2) {
bytes[i / 2] = parseInt(hex.substring(i, i + 2), 16);
}
return bytes;
}
function downloadMainKey(){
// 创建一个Blob对象
const bytes = hexToBytes(window.mkd);
const blob = new Blob([bytes], { type: 'application/octet-stream' });
// 生成一个临时的URL
const blobUrl = URL.createObjectURL(blob);
// 创建一个a标签并设置为下载链接
const downloadLink = document.createElement('a');
downloadLink.href = blobUrl;
downloadLink.download = 'MainKey.Dat'; // 指定下载文件的名称
// 触发a标签的点击事件以开始下载
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);
// 清理URL
URL.revokeObjectURL(blobUrl);
}
function checkValue(p1, p2, p3){
const protectKey = window.gmhelper.xor(p1, p2, p3)
const protectKcv = window.gmhelper.kcv( protectKey )
if ( protectKcv.toUpperCase().substr(0, 8) != window.mk.weight0x50.toUpperCase()) {
alert('保护密钥校验值错误!!!')
return false
}
var finalMainKey = window.gmhelper.decryptKey(window.mk.weight0x40 , protectKey) // 解密
const mainKcv = window.gmhelper.kcv( finalMainKey )
if ( mainKcv.toUpperCase().substr(0, 8) !== window.mk.weight0x30.toUpperCase()) {
alert('主密钥校验值错误!!!')
return false
}
return finalMainKey;
}
</script>
</body>
</html>