完成协议开发
This commit is contained in:
parent
422d44df1b
commit
00de726082
@ -1,6 +1,8 @@
|
|||||||
# Fake UKey
|
# Fake UKey
|
||||||
|
|
||||||
1. 暂时无法实现 UKEY 复制, 只能从初始化时就使用 Fake UKEY。
|
1. 与渔翁 UKEY 协议完全兼容。内置 7 个虚拟 UKEY。
|
||||||
|
2. 与渔翁 UKEY 驱动冲突。启动时会尝试强制剔除渔翁 UKEY,但是建议手工退出渔翁 UKEY 驱动。
|
||||||
|
3. 暂时无法实现 UKEY 复制, 只能从初始化时就使用 Fake UKEY。
|
||||||
|
|
||||||
|
|
||||||
## API
|
## API
|
||||||
|
265
backend/src/FakeUKey.js
Normal file
265
backend/src/FakeUKey.js
Normal file
@ -0,0 +1,265 @@
|
|||||||
|
const config = require("./Config")
|
||||||
|
const fs = require("fs")
|
||||||
|
const path = require("path");
|
||||||
|
|
||||||
|
|
||||||
|
function listFakeUKeys(){
|
||||||
|
let ukeyDir = config.getFakeUKeyDir();
|
||||||
|
const files = fs.readdirSync(ukeyDir);
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkFakeUKey(name){
|
||||||
|
let ukeyDir = config.getFakeUKeyDir();
|
||||||
|
return fs.existsSync(path.resolve(ukeyDir, name))
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkUKeyPIN(dev, pin) {
|
||||||
|
let ukeyDir = config.getFakeUKeyDir();
|
||||||
|
let ppin = fs.readFileSync(path.resolve(ukeyDir, dev, "pin.txt"), "utf-8")
|
||||||
|
return pin === ppin
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
// 枚举设备
|
||||||
|
"01000005" : function () {
|
||||||
|
|
||||||
|
let nameList = listFakeUKeys()
|
||||||
|
|
||||||
|
return {
|
||||||
|
"EnumDeviceNameList": nameList.join("|"),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 打开设备
|
||||||
|
"01000004" : function (params) {
|
||||||
|
let ukey = params.devSerial
|
||||||
|
if ( checkFakeUKey( ukey ) ) {
|
||||||
|
return {"hdev": ukey}
|
||||||
|
} else {
|
||||||
|
throw "找不到设备"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// PIN 登录
|
||||||
|
"01000027" : function (params) {
|
||||||
|
let ukey = params.hdevice
|
||||||
|
let pin = params.pin
|
||||||
|
if ( checkUKeyPIN(ukey, pin) ) {
|
||||||
|
return {"huser":"", "count":0, "rev":0}
|
||||||
|
} else {
|
||||||
|
throw "PIN 验证错误"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 文件系统初始化
|
||||||
|
"01000031" : function (params) {
|
||||||
|
let ukey = params.hdevice
|
||||||
|
if ( fs.existsSync(path.resolve(config.getFakeUKeyDir(), ukey, "root")) ) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
throw "目录损坏"
|
||||||
|
},
|
||||||
|
|
||||||
|
// 创建目录
|
||||||
|
"01000032" : function (params) {
|
||||||
|
let ukey = params.hdevice
|
||||||
|
let dir = params.dir
|
||||||
|
let acc = params.acc
|
||||||
|
|
||||||
|
if ( dir.startsWith("\\root\\") ) {
|
||||||
|
dir = dir.substring(6);
|
||||||
|
fs.mkdirSync(path.resolve(config.getFakeUKeyDir(), ukey, "root", dir), { recursive: true });
|
||||||
|
return {}
|
||||||
|
} else {
|
||||||
|
throw "目录不合法"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 创建文件
|
||||||
|
"01000034" : function (params) {
|
||||||
|
let ukey = params.hdevice
|
||||||
|
let dir = params.dir
|
||||||
|
let file = params.file
|
||||||
|
let size = params.size
|
||||||
|
let acc = params.acc
|
||||||
|
|
||||||
|
if ( dir.startsWith("\\root\\") ) {
|
||||||
|
dir = dir.substring(6);
|
||||||
|
if ( fs.existsSync(path.resolve(config.getFakeUKeyDir(), ukey, "root", dir)) ) {
|
||||||
|
// throw "文件已存在"
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw "目录不合法"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 读取文件
|
||||||
|
"01000035" : function (params) {
|
||||||
|
let ukey = params.hdevice
|
||||||
|
let dir = params.dir
|
||||||
|
let file = params.file
|
||||||
|
let size = parseInt(params.size, 10)
|
||||||
|
let offset = parseInt(params.offset, 10)
|
||||||
|
|
||||||
|
if ( dir.startsWith("\\root\\") ) {
|
||||||
|
dir = dir.substring(6);
|
||||||
|
let f = path.resolve(config.getFakeUKeyDir(), ukey, "root\\", dir, file)
|
||||||
|
let buffer = fs.readFileSync(f);
|
||||||
|
return {
|
||||||
|
data : buffer.slice(offset, offset + size).toString("HEX").toUpperCase()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw "目录不合法"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 写入文件
|
||||||
|
"01000036" : function (params) {
|
||||||
|
let ukey = params.hdevice
|
||||||
|
let dir = params.dir
|
||||||
|
let file = params.file
|
||||||
|
let size = params.size
|
||||||
|
let offset = parseInt(params.offset, 10)
|
||||||
|
let input = params.input
|
||||||
|
|
||||||
|
if ( dir.startsWith("\\root\\") ) {
|
||||||
|
dir = dir.substring(6);
|
||||||
|
let f = path.resolve(config.getFakeUKeyDir(), ukey, "root\\", dir, file)
|
||||||
|
let buffer = undefined;
|
||||||
|
if ( offset === 0 ) {
|
||||||
|
buffer = Buffer.from(input, 'hex');
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if ( fs.existsSync( f ) ) {
|
||||||
|
buffer = fs.readFileSync(f);
|
||||||
|
buffer = buffer.slice(0, offset);
|
||||||
|
} else {
|
||||||
|
buffer = Buffer.alloc(offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = Buffer.concat([buffer, Buffer.from(input, 'hex')])
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.writeFileSync(f, buffer)
|
||||||
|
return {}
|
||||||
|
} else {
|
||||||
|
throw "目录不合法"
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
// 删除文件
|
||||||
|
"01000037" : function (params) {
|
||||||
|
let ukey = params.hdevice
|
||||||
|
let dir = params.dir
|
||||||
|
let file = params.file
|
||||||
|
|
||||||
|
if ( ! dir.startsWith("\\root\\") ) {
|
||||||
|
throw "目录不合法"
|
||||||
|
}
|
||||||
|
|
||||||
|
dir = dir.substring(6);
|
||||||
|
let f = path.resolve(config.getFakeUKeyDir(), ukey, "root\\", dir, file)
|
||||||
|
fs.unlinkSync( f )
|
||||||
|
|
||||||
|
return {}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 枚举文件夹
|
||||||
|
"01000038" : function (params) {
|
||||||
|
let ukey = params.hdevice
|
||||||
|
let dir = params.dir
|
||||||
|
|
||||||
|
if ( ! dir.startsWith("\\root\\") ) {
|
||||||
|
throw "目录不合法"
|
||||||
|
}
|
||||||
|
|
||||||
|
dir = dir.substring(6);
|
||||||
|
let f = path.resolve(config.getFakeUKeyDir(), ukey, "root\\", dir)
|
||||||
|
let list = fs.readdirSync(f)
|
||||||
|
let files = []
|
||||||
|
for ( let fname of list ) {
|
||||||
|
let p = path.resolve(f, fname)
|
||||||
|
if ( fs.statSync( p ).isFile() ) {
|
||||||
|
files.push( fname )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
// 枚举文件
|
||||||
|
"01000039" : function (params) {
|
||||||
|
let ukey = params.hdevice
|
||||||
|
let dir = params.dir
|
||||||
|
|
||||||
|
if ( ! dir.startsWith("\\root\\") ) {
|
||||||
|
throw "目录不合法"
|
||||||
|
}
|
||||||
|
|
||||||
|
dir = dir.substring(6);
|
||||||
|
let f = path.resolve(config.getFakeUKeyDir(), ukey, "root\\", dir)
|
||||||
|
let list = fs.readdirSync(f)
|
||||||
|
let files = []
|
||||||
|
for ( let fname of list ) {
|
||||||
|
let p = path.resolve(f, fname)
|
||||||
|
if ( ! fs.statSync( p ).isFile() ) {
|
||||||
|
files.push( fname )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 生成密钥对
|
||||||
|
"01000040" : function (params) {
|
||||||
|
let ukey = params.hdevice
|
||||||
|
let alg = params.alg
|
||||||
|
let keyNum = params.keyNum
|
||||||
|
let keyLen = params.keyLen
|
||||||
|
|
||||||
|
const sm2 = require('sm-crypto').sm2
|
||||||
|
|
||||||
|
let keypair = sm2.generateKeyPairHex()
|
||||||
|
|
||||||
|
let ukeyDir = config.getFakeUKeyDir();
|
||||||
|
fs.writeFileSync(path.resolve(ukeyDir, ukey, keyNum + ".key"), JSON.stringify(keypair, null, 4))
|
||||||
|
|
||||||
|
return {}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
// 导出公钥
|
||||||
|
"01000043" : function (params) {
|
||||||
|
let ukey = params.hdevice
|
||||||
|
let keyNum = params.keyNum
|
||||||
|
|
||||||
|
let ukeyDir = config.getFakeUKeyDir();
|
||||||
|
let keyJson = fs.readFileSync(path.resolve(ukeyDir, ukey, keyNum + ".key"), "UTF-8")
|
||||||
|
let key = JSON.parse(keyJson)
|
||||||
|
let pubkey = Buffer.from(key.publicKey, "hex").toString("base64")
|
||||||
|
return {
|
||||||
|
keyData : "-----BEGIN ECDSA PUBLIC KEY-----" + pubkey + "-----END ECDSA PUBLIC KEY-----"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 签名
|
||||||
|
"01000046" : function (params) {
|
||||||
|
let ukey = params.hdevice
|
||||||
|
let keyNum = params.keyNum
|
||||||
|
let inData = params.inData
|
||||||
|
|
||||||
|
let ukeyDir = config.getFakeUKeyDir();
|
||||||
|
let keyJson = fs.readFileSync(path.resolve(ukeyDir, ukey, keyNum + ".key"), "UTF-8")
|
||||||
|
let key = JSON.parse(keyJson)
|
||||||
|
|
||||||
|
let sigValueHex = sm2.doSignature(Buffer.from(inData, "base64"), key.privateKey) // 签名
|
||||||
|
|
||||||
|
return {
|
||||||
|
sigData : Buffer.from(sigValueHex, "HEX").toString("base64")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,11 +1,18 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const bodyParser = require('body-parser');
|
const bodyParser = require('body-parser');
|
||||||
|
const ukey = require("./FakeUKey")
|
||||||
|
const cors = require('cors');
|
||||||
|
const { killPortProcess } = require('kill-port-process');
|
||||||
|
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
const port = 3000;
|
// const port = 3000;
|
||||||
|
const port = 8090;
|
||||||
|
|
||||||
// 使用body-parser中间件来解析urlencoded格式的请求体
|
// 使用body-parser中间件来解析urlencoded格式的请求体
|
||||||
app.use(bodyParser.urlencoded({ extended: true }));
|
app.use(bodyParser.urlencoded({ extended: true }));
|
||||||
|
app.use(cors());
|
||||||
|
|
||||||
|
|
||||||
app.get("/", (req, res) => {
|
app.get("/", (req, res) => {
|
||||||
res.json({
|
res.json({
|
||||||
@ -15,13 +22,43 @@ app.get("/", (req, res) => {
|
|||||||
})
|
})
|
||||||
app.post('/do', (req, res) => {
|
app.post('/do', (req, res) => {
|
||||||
// 获取请求体中的数据
|
// 获取请求体中的数据
|
||||||
const requestData = req.body;
|
let requestData = {
|
||||||
|
"rev": -1
|
||||||
|
};
|
||||||
|
|
||||||
|
let func = ukey[ req.body.order ]
|
||||||
|
if ( func ){
|
||||||
|
try {
|
||||||
|
let ret = func(req.body)
|
||||||
|
requestData = Object.assign(ret, {
|
||||||
|
"rev": 0
|
||||||
|
})
|
||||||
|
} catch ( e ) {
|
||||||
|
console.error( e )
|
||||||
|
requestData.msg = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 设置响应类型为application/x-json
|
// 设置响应类型为application/x-json
|
||||||
res.setHeader('Content-Type', 'application/x-json'); // 注意application/x-json不是标准MIME类型,通常使用application/json
|
res.setHeader('Content-Type', 'application/x-json'); // 注意application/x-json不是标准MIME类型,通常使用application/json
|
||||||
// 将请求的数据返回为json格式的响应体
|
// 将请求的数据返回为json格式的响应体
|
||||||
res.json(requestData);
|
res.json(requestData);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
|
||||||
|
try {
|
||||||
|
await killPortProcess(port);
|
||||||
|
} catch (e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
app.listen(port, () => {
|
app.listen(port, () => {
|
||||||
console.log(`Server is running on port ${port}`);
|
console.log(`Server is running on port ${port}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user