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