parent
ca29e475b8
commit
4993fe2b51
@ -1,160 +1,160 @@ |
|||||||
import CryptoJS from 'crypto-js' |
// import CryptoJS from 'crypto-js'
|
||||||
import forge from 'node-forge' |
// import forge from 'node-forge'
|
||||||
import JSEncrypt from 'jsencrypt' |
// import JSEncrypt from 'jsencrypt'
|
||||||
|
|
||||||
const DEFAULT_PUBLIC_KEY = { |
// const DEFAULT_PUBLIC_KEY = {
|
||||||
//pubN:
|
// //pubN:
|
||||||
// 'a8e745832ad4792735a3113ab103f5622222449dfcb68c69008f9f3452943e555749a607a6147bb79db1779a645944caa1314a077e0ffc48dfd9c2a6b5fb121e7909d84b88c02e8019746dcbb9339c037ab31ab3620524f6c61bdedaf8d68277dc59a9b0bcf804757db40b7687d9b95a7b15504073fd87c58698441d577d4bab',
|
// // 'a8e745832ad4792735a3113ab103f5622222449dfcb68c69008f9f3452943e555749a607a6147bb79db1779a645944caa1314a077e0ffc48dfd9c2a6b5fb121e7909d84b88c02e8019746dcbb9339c037ab31ab3620524f6c61bdedaf8d68277dc59a9b0bcf804757db40b7687d9b95a7b15504073fd87c58698441d577d4bab',
|
||||||
pubN: 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCo3O/QrFgmor+MsUZ5iWKmINK0c6nI+cEguJHjuJzeP52vMfHlsyyXgkCaI62xUAUWVjbeCD4UIFph07c0AjYtGp/r5V3V9oAtcU9w9nXa43bqprTrSbasXZpK+BVG4xZXf448pG3G5tUNyzLTm4pRt2Z3Q9OJ3IEzkrRAvCHIPQIDAQAB', |
// pubN: 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCo3O/QrFgmor+MsUZ5iWKmINK0c6nI+cEguJHjuJzeP52vMfHlsyyXgkCaI62xUAUWVjbeCD4UIFph07c0AjYtGp/r5V3V9oAtcU9w9nXa43bqprTrSbasXZpK+BVG4xZXf448pG3G5tUNyzLTm4pRt2Z3Q9OJ3IEzkrRAvCHIPQIDAQAB',
|
||||||
pubE: '10001', |
// pubE: '10001',
|
||||||
encCertSN: '1021020000067221ed', |
// encCertSN: '1021020000067221ed',
|
||||||
} |
// }
|
||||||
|
|
||||||
function stripImagePrefix(value) { |
// function stripImagePrefix(value) {
|
||||||
return value.replace(/^data:image\/[a-zA-Z0-9.+-]+;base64,/, '') |
// return value.replace(/^data:image\/[a-zA-Z0-9.+-]+;base64,/, '')
|
||||||
} |
// }
|
||||||
|
|
||||||
function normalizeContexts(contexts, stripPrefix = false) { |
// function normalizeContexts(contexts, stripPrefix = false) {
|
||||||
const source = contexts || {} |
// const source = contexts || {}
|
||||||
|
|
||||||
if (Array.isArray(source)) { |
// if (Array.isArray(source)) {
|
||||||
return source |
// return source
|
||||||
.filter( |
// .filter(
|
||||||
(item) => |
// (item) =>
|
||||||
item && |
// item &&
|
||||||
item.cid !== undefined && |
// item.cid !== undefined &&
|
||||||
item.cid !== null && |
// item.cid !== null &&
|
||||||
item.value !== undefined && |
// item.value !== undefined &&
|
||||||
item.value !== null, |
// item.value !== null,
|
||||||
) |
// )
|
||||||
.map(({ cid, value }) => { |
// .map(({ cid, value }) => {
|
||||||
const normalizedValue = stripPrefix ? stripImagePrefix(String(value)) : String(value) |
// const normalizedValue = stripPrefix ? stripImagePrefix(String(value)) : String(value)
|
||||||
return `<Context ID="${cid}">${normalizedValue}</Context>` |
// return `<Context ID="${cid}">${normalizedValue}</Context>`
|
||||||
}) |
// })
|
||||||
.join('') |
// .join('')
|
||||||
} |
// }
|
||||||
|
|
||||||
return Object.keys(source) |
// return Object.keys(source)
|
||||||
.filter((cid) => source[cid] !== undefined && source[cid] !== null) |
// .filter((cid) => source[cid] !== undefined && source[cid] !== null)
|
||||||
.map((cid) => { |
// .map((cid) => {
|
||||||
const rawValue = String(source[cid]) |
// const rawValue = String(source[cid])
|
||||||
const normalizedValue = stripPrefix ? stripImagePrefix(rawValue) : rawValue |
// const normalizedValue = stripPrefix ? stripImagePrefix(rawValue) : rawValue
|
||||||
return `<Context ID="${cid}">${normalizedValue}</Context>` |
// return `<Context ID="${cid}">${normalizedValue}</Context>`
|
||||||
}) |
// })
|
||||||
.join('') |
// .join('')
|
||||||
} |
// }
|
||||||
|
|
||||||
function getRandomBytes(length) { |
// function getRandomBytes(length) {
|
||||||
const randomBytes = new Uint8Array(length) |
// const randomBytes = new Uint8Array(length)
|
||||||
const cryptoProvider = globalThis.crypto || globalThis['msCrypto'] |
// const cryptoProvider = globalThis.crypto || globalThis['msCrypto']
|
||||||
|
|
||||||
if (!cryptoProvider || typeof cryptoProvider.getRandomValues !== 'function') { |
// if (!cryptoProvider || typeof cryptoProvider.getRandomValues !== 'function') {
|
||||||
throw new Error('当前环境不支持生成随机密钥') |
// throw new Error('当前环境不支持生成随机密钥')
|
||||||
} |
// }
|
||||||
|
|
||||||
cryptoProvider.getRandomValues(randomBytes) |
// cryptoProvider.getRandomValues(randomBytes)
|
||||||
return randomBytes |
// return randomBytes
|
||||||
} |
// }
|
||||||
|
|
||||||
function uint8ArrayToHex(uint8Array) { |
// function uint8ArrayToHex(uint8Array) {
|
||||||
return Array.from(uint8Array, (byte) => byte.toString(16).padStart(2, '0')).join('') |
// return Array.from(uint8Array, (byte) => byte.toString(16).padStart(2, '0')).join('')
|
||||||
} |
// }
|
||||||
|
|
||||||
function uint8ArrayToBinaryString(uint8Array) { |
// function uint8ArrayToBinaryString(uint8Array) {
|
||||||
return Array.from(uint8Array, (byte) => String.fromCharCode(byte)).join('') |
// return Array.from(uint8Array, (byte) => String.fromCharCode(byte)).join('')
|
||||||
} |
// }
|
||||||
function rsaPubkeyUint8EncByDefault(uint8Array, pubN) { |
// function rsaPubkeyUint8EncByDefault(uint8Array, pubN) {
|
||||||
var encrypt = new JSEncrypt() |
// var encrypt = new JSEncrypt()
|
||||||
|
|
||||||
// 设置公钥
|
// // 设置公钥
|
||||||
encrypt.setPublicKey(pubN) |
// encrypt.setPublicKey(pubN)
|
||||||
|
|
||||||
// 加密
|
// // 加密
|
||||||
var encrypted = encrypt.encrypt(uint8Array) |
// var encrypted = encrypt.encrypt(uint8Array)
|
||||||
|
|
||||||
// 输出加密结果(Base64编码的字符串)
|
// // 输出加密结果(Base64编码的字符串)
|
||||||
// console.log("加密后的密文:", encrypted);
|
// // console.log("加密后的密文:", encrypted);
|
||||||
return encrypted |
// return encrypted
|
||||||
|
|
||||||
//return rsaPubkeyUint8Enc(pubN, pubE, uint8Array)
|
// //return rsaPubkeyUint8Enc(pubN, pubE, uint8Array)
|
||||||
} |
// }
|
||||||
function encryptRandomKey(randomBytes, pubN, pubE) { |
// function encryptRandomKey(randomBytes, pubN, pubE) {
|
||||||
const modulus = new forge.jsbn.BigInteger(pubN, 16) |
// const modulus = new forge.jsbn.BigInteger(pubN, 16)
|
||||||
const exponent = new forge.jsbn.BigInteger(pubE, 16) |
// const exponent = new forge.jsbn.BigInteger(pubE, 16)
|
||||||
const publicKey = forge.pki.setRsaPublicKey(modulus, exponent) |
// const publicKey = forge.pki.setRsaPublicKey(modulus, exponent)
|
||||||
const encryptedBinary = publicKey.encrypt( |
// const encryptedBinary = publicKey.encrypt(
|
||||||
uint8ArrayToBinaryString(randomBytes), |
// uint8ArrayToBinaryString(randomBytes),
|
||||||
'RSAES-PKCS1-V1_5', |
// 'RSAES-PKCS1-V1_5',
|
||||||
) |
// )
|
||||||
|
|
||||||
return forge.util.encode64(encryptedBinary) |
// return forge.util.encode64(encryptedBinary)
|
||||||
} |
// }
|
||||||
|
|
||||||
function encryptPayload(payload, randomBytes) { |
// function encryptPayload(payload, randomBytes) {
|
||||||
const key = CryptoJS.enc.Hex.parse(uint8ArrayToHex(randomBytes)) |
// const key = CryptoJS.enc.Hex.parse(uint8ArrayToHex(randomBytes))
|
||||||
return String( |
// return String(
|
||||||
CryptoJS.TripleDES.encrypt(payload, key, { |
// CryptoJS.TripleDES.encrypt(payload, key, {
|
||||||
mode: CryptoJS.mode.ECB, |
// mode: CryptoJS.mode.ECB,
|
||||||
padding: CryptoJS.pad.Pkcs7, |
// padding: CryptoJS.pad.Pkcs7,
|
||||||
}), |
// }),
|
||||||
) |
// )
|
||||||
} |
// }
|
||||||
|
|
||||||
export function buildEncryptedAnysignXml({ |
// export function buildEncryptedAnysignXml({
|
||||||
tid, |
// tid,
|
||||||
signContexts = {}, |
// signContexts = {},
|
||||||
dataContexts = {}, |
// dataContexts = {},
|
||||||
deviceInfo = {}, |
// deviceInfo = {},
|
||||||
randomBytes, |
// randomBytes,
|
||||||
publicKey = DEFAULT_PUBLIC_KEY, |
// publicKey = DEFAULT_PUBLIC_KEY,
|
||||||
} = {}) { |
// } = {}) {
|
||||||
if (tid === undefined || tid === null || tid === '') { |
// if (tid === undefined || tid === null || tid === '') {
|
||||||
throw new Error('tid 不能为空') |
// throw new Error('tid 不能为空')
|
||||||
} |
// }
|
||||||
|
|
||||||
const toEnc = `<Data>${normalizeContexts(signContexts, true)}${normalizeContexts(dataContexts)}</Data>` |
// const toEnc = `<Data>${normalizeContexts(signContexts, true)}${normalizeContexts(dataContexts)}</Data>`
|
||||||
const random = randomBytes instanceof Uint8Array ? randomBytes : getRandomBytes(24) |
// const random = randomBytes instanceof Uint8Array ? randomBytes : getRandomBytes(24)
|
||||||
|
|
||||||
if (random.length !== 24) { |
// if (random.length !== 24) {
|
||||||
throw new Error('randomBytes 必须是 24 字节') |
// throw new Error('randomBytes 必须是 24 字节')
|
||||||
} |
// }
|
||||||
|
|
||||||
// const encKey = encryptRandomKey(random, publicKey.pubN, publicKey.pubE)
|
// // const encKey = encryptRandomKey(random, publicKey.pubN, publicKey.pubE)
|
||||||
const encKey = rsaPubkeyUint8EncByDefault(uint8ArrayToHex(random), publicKey.pubN) |
// const encKey = rsaPubkeyUint8EncByDefault(uint8ArrayToHex(random), publicKey.pubN)
|
||||||
const encData = encryptPayload(toEnc, random) |
// const encData = encryptPayload(toEnc, random)
|
||||||
const deviceMF = deviceInfo.appName || navigator.appName |
// const deviceMF = deviceInfo.appName || navigator.appName
|
||||||
const deviceOS = deviceInfo.platform || navigator.platform |
// const deviceOS = deviceInfo.platform || navigator.platform
|
||||||
const deviceSN = deviceInfo.appVersion || navigator.appVersion |
// const deviceSN = deviceInfo.appVersion || navigator.appVersion
|
||||||
|
|
||||||
let root = '<?xml version="1.0" encoding="UTF-8"?>' |
// let root = '<?xml version="1.0" encoding="UTF-8"?>'
|
||||||
root += '<BJCAROOT>' |
// root += '<BJCAROOT>'
|
||||||
root += '<Version>1</Version>' |
// root += '<Version>1</Version>'
|
||||||
root += `<SignTID>${tid}</SignTID>` |
// root += `<SignTID>${tid}</SignTID>`
|
||||||
root += `<EncKey>${encKey}</EncKey>` |
// root += `<EncKey>${encKey}</EncKey>`
|
||||||
root += '<Cert>' |
// root += '<Cert>'
|
||||||
root += `<EncCertSN>${publicKey.encCertSN}</EncCertSN>` |
// root += `<EncCertSN>${publicKey.encCertSN}</EncCertSN>`
|
||||||
root += '<EncCertKeyID>N/A</EncCertKeyID>' |
// root += '<EncCertKeyID>N/A</EncCertKeyID>'
|
||||||
root += '<EncAlg>1</EncAlg>' |
// root += '<EncAlg>1</EncAlg>'
|
||||||
root += '</Cert>' |
// root += '</Cert>'
|
||||||
root += `<EncData>${encData}</EncData>` |
// root += `<EncData>${encData}</EncData>`
|
||||||
root += `<DeviceInfo><DeviceMF>${deviceMF}</DeviceMF><DeivceOS>${deviceOS}</DeivceOS><DeiviceSN>${deviceSN}</DeiviceSN></DeviceInfo>` |
// root += `<DeviceInfo><DeviceMF>${deviceMF}</DeviceMF><DeivceOS>${deviceOS}</DeivceOS><DeiviceSN>${deviceSN}</DeiviceSN></DeviceInfo>`
|
||||||
root += '<SignCertSN>NA</SignCertSN>' |
// root += '<SignCertSN>NA</SignCertSN>'
|
||||||
root += '<SignValue>NULL</SignValue>' |
// root += '<SignValue>NULL</SignValue>'
|
||||||
root += '</BJCAROOT>' |
// root += '</BJCAROOT>'
|
||||||
|
|
||||||
return root |
// return root
|
||||||
} |
// }
|
||||||
// import { buildEncryptedAnysignXml } from '@/utils/anysignXml.js'
|
// // import { buildEncryptedAnysignXml } from '@/utils/anysignXml.js'
|
||||||
|
|
||||||
// const xml = buildEncryptedAnysignXml({
|
// // const xml = buildEncryptedAnysignXml({
|
||||||
// tid: '20011',
|
// // tid: '20011',
|
||||||
// signContexts: {
|
// // signContexts: {
|
||||||
// 22: 'data:image/png;base64,iVBORw0KGgoAAA...',
|
// // 22: 'data:image/png;base64,iVBORw0KGgoAAA...',
|
||||||
// },
|
// // },
|
||||||
// dataContexts: {
|
// // dataContexts: {
|
||||||
// 13: JSON.stringify({ foo: 'bar' }),
|
// // 13: JSON.stringify({ foo: 'bar' }),
|
||||||
// 14: JSON.stringify({ userName: '张三' }),
|
// // 14: JSON.stringify({ userName: '张三' }),
|
||||||
// 15: 'hash',
|
// // 15: 'hash',
|
||||||
// 16: '1000105',
|
// // 16: '1000105',
|
||||||
// },
|
// // },
|
||||||
// })
|
// // })
|
||||||
|
|||||||
@ -1,71 +1,71 @@ |
|||||||
import smCrypto from 'sm-crypto' |
// import smCrypto from 'sm-crypto'
|
||||||
|
|
||||||
const { sm4 } = smCrypto |
// const { sm4 } = smCrypto
|
||||||
const currentHostname = window.location.hostname |
// const currentHostname = window.location.hostname
|
||||||
|
|
||||||
export const SM4_SAMPLE_CONFIG = { |
// export const SM4_SAMPLE_CONFIG = {
|
||||||
cipherTextBase64: 'At1K/lI9/xqGNOqc7LMKVw==', |
// cipherTextBase64: 'At1K/lI9/xqGNOqc7LMKVw==',
|
||||||
keyHex: stringToHex( |
// keyHex: stringToHex(
|
||||||
currentHostname.includes('localhost') || currentHostname.includes('aioblu-dev.trace.com.cn') |
// currentHostname.includes('localhost') || currentHostname.includes('aioblu-dev.trace.com.cn')
|
||||||
? '0123456789abcdef' || 'a1b2c3d4e5f67890' |
// ? '0123456789abcdef' || 'a1b2c3d4e5f67890'
|
||||||
: currentHostname.includes('aioblu-sit.trace.com.cn') |
// : currentHostname.includes('aioblu-sit.trace.com.cn')
|
||||||
? '9f8e7d6c5b4a3210' |
// ? '9f8e7d6c5b4a3210'
|
||||||
: '7h9k2m5n8p1q4r6s', |
// : '7h9k2m5n8p1q4r6s',
|
||||||
), |
// ),
|
||||||
ivHex: stringToHex( |
// ivHex: stringToHex(
|
||||||
currentHostname.includes('localhost') || currentHostname.includes('aioblu-dev.trace.com.cn') |
// currentHostname.includes('localhost') || currentHostname.includes('aioblu-dev.trace.com.cn')
|
||||||
? 'abcdef0123456789' || '1a2b3c4d5e6f7089' |
// ? 'abcdef0123456789' || '1a2b3c4d5e6f7089'
|
||||||
: currentHostname.includes('aioblu-sit.trace.com.cn') |
// : currentHostname.includes('aioblu-sit.trace.com.cn')
|
||||||
? '0123456789abcdef' |
// ? '0123456789abcdef'
|
||||||
: '3t6w9z2b5e8h1k4n', |
// : '3t6w9z2b5e8h1k4n',
|
||||||
), |
// ),
|
||||||
} |
// }
|
||||||
function stringToHex(str) { |
// function stringToHex(str) {
|
||||||
return Array.from(str) |
// return Array.from(str)
|
||||||
.map((c) => c.charCodeAt(0).toString(16).padStart(2, '0')) |
// .map((c) => c.charCodeAt(0).toString(16).padStart(2, '0'))
|
||||||
.join('') |
// .join('')
|
||||||
} |
// }
|
||||||
function base64ToHex(base64) { |
// function base64ToHex(base64) {
|
||||||
const binary = atob(base64) |
// const binary = atob(base64)
|
||||||
let hex = '' |
// let hex = ''
|
||||||
|
|
||||||
for (let i = 0; i < binary.length; i += 1) { |
// for (let i = 0; i < binary.length; i += 1) {
|
||||||
hex += binary.charCodeAt(i).toString(16).padStart(2, '0') |
// hex += binary.charCodeAt(i).toString(16).padStart(2, '0')
|
||||||
} |
// }
|
||||||
|
|
||||||
return hex |
// return hex
|
||||||
} |
// }
|
||||||
|
|
||||||
export function decryptSm4EcbBase64(cipherTextBase64) { |
// export function decryptSm4EcbBase64(cipherTextBase64) {
|
||||||
try { |
// try {
|
||||||
const cipherHex = base64ToHex(cipherTextBase64) |
// const cipherHex = base64ToHex(cipherTextBase64)
|
||||||
return sm4.decrypt( |
// return sm4.decrypt(
|
||||||
cipherHex, |
// cipherHex,
|
||||||
SM4_SAMPLE_CONFIG.keyHex, |
// SM4_SAMPLE_CONFIG.keyHex,
|
||||||
// { padding: 'none' }
|
// // { padding: 'none' }
|
||||||
) |
// )
|
||||||
} catch (error) { |
// } catch (error) {
|
||||||
console.log('cipherTextBase64', cipherTextBase64) |
// console.log('cipherTextBase64', cipherTextBase64)
|
||||||
const cipherHex = base64ToHex(cipherTextBase64) |
// const cipherHex = base64ToHex(cipherTextBase64)
|
||||||
try { |
// try {
|
||||||
return sm4.decrypt(cipherHex, SM4_SAMPLE_CONFIG.keyHex, { padding: 'none' }) |
// return sm4.decrypt(cipherHex, SM4_SAMPLE_CONFIG.keyHex, { padding: 'none' })
|
||||||
} catch (error) { |
// } catch (error) {
|
||||||
return cipherHex |
// return cipherHex
|
||||||
} |
// }
|
||||||
} |
// }
|
||||||
} |
// }
|
||||||
|
|
||||||
export function decryptSm4CbcBase64(cipherTextBase64, keyHex, ivHex) { |
// export function decryptSm4CbcBase64(cipherTextBase64, keyHex, ivHex) {
|
||||||
const cipherHex = base64ToHex(cipherTextBase64) |
// const cipherHex = base64ToHex(cipherTextBase64)
|
||||||
|
|
||||||
return sm4.decrypt(cipherHex, keyHex, { |
// return sm4.decrypt(cipherHex, keyHex, {
|
||||||
mode: 'cbc', |
// mode: 'cbc',
|
||||||
iv: ivHex, |
// iv: ivHex,
|
||||||
}) |
// })
|
||||||
} |
// }
|
||||||
|
|
||||||
export function decryptCurrentSample() { |
// export function decryptCurrentSample() {
|
||||||
return decryptSm4EcbBase64(SM4_SAMPLE_CONFIG.cipherTextBase64, SM4_SAMPLE_CONFIG.keyHex) |
// return decryptSm4EcbBase64(SM4_SAMPLE_CONFIG.cipherTextBase64, SM4_SAMPLE_CONFIG.keyHex)
|
||||||
} |
// }
|
||||||
|
|
||||||
export const CURRENT_SAMPLE_PLAIN_TEXT = decryptCurrentSample() |
// export const CURRENT_SAMPLE_PLAIN_TEXT = decryptCurrentSample()
|
||||||
|
|||||||
Loading…
Reference in new issue