247 lines
8.8 KiB
Vue
247 lines
8.8 KiB
Vue
<template>
|
||
<view class="content">
|
||
<button @click="randomBytes" style="background:#Fc4e2b">crypto.randomBytes (微信小程序失败)</button>
|
||
<button @click="scrypt" style="background:#Fc4e2b">crypto.scryptSync (全部失败)</button>
|
||
<!-- <button @click="secureRandom">secure-random库生成随机字节</button> -->
|
||
<button @click="generateMnemonic" style="background:#Fc4e2b">bip39 生成助记词 (微信小程序失败)</button>
|
||
<!-- <button @click="test4">bitcore-mnemonic库生成助记词</button>
|
||
-->
|
||
<button @click="mnemonic2seed" style="background:#Fc4e2b">bip39 从助记词到种子(安卓失败)</button>
|
||
<button @click="validateMnemonic" style="background:#Fc4e2b">bip39 验证助记词(安卓失败)</button>
|
||
<button @click="prikey2pubkey" style="background:#Fc4e2b">crypto 私钥转公钥(安卓、ios、微信失败)</button>
|
||
<view style="display:flex; flex-flow:row; width:100%;">
|
||
<button @click="encrypt">crypto对称加密</button>
|
||
<button @click="decrypt">crypto对称解密</button>
|
||
</view>
|
||
<view style="display:flex; flex-flow:row; width:100%;">
|
||
<button @click="sign">crypto不对称签名</button>
|
||
<button @click="verify">crypto不对称验签</button>
|
||
</view>
|
||
<view style="display:flex; flex-flow:row; width:100%;">
|
||
<button @click="encryptECC">ECC不对称加密</button>
|
||
<button @click="decryptECC">ECC不对称解密</button>
|
||
</view>
|
||
<view style="display:flex; flex-flow:row; width:100%;">
|
||
<button @click="signECC">ECC不对称签名</button>
|
||
<button @click="verifyECC">ECC不对称验签</button>
|
||
</view>
|
||
<view class="text-area">
|
||
<text class="title">{{ JSON.stringify(title) }}</text>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import crypto from 'crypto';
|
||
import ticc from 'tic-crypto';
|
||
import secureRandom from 'secure-random';
|
||
import secp256k1 from 'secp256k1';
|
||
import hdkey from 'hdkey';
|
||
import * as bip39 from 'bip39';
|
||
//import * as eccrypto from 'eccrypto-js'; // 签名在浏览器/苹果里都成功。加解密都失败。
|
||
import eccrypto from 'eccrypto'; // 签名在浏览器/苹果里都成功。encrypt/decrypt在苹果手机里成功,在浏览器里 失败
|
||
import keyman from 'js-crypto-key-utils';
|
||
|
||
const keypair = { prikey: '872d58c1f872636cf2ca460e85f27eb98f4a1fd5f5b70ea702a52c9bf28252ae', pubkey: '03883e6c412431729c78236f7fd6e663c92a863414d7047535b3b386a6410bf331' };
|
||
const mnemonic = '滴 民 延 腹 召 罩 巧 舟 小 顶 辩 资';
|
||
const signature = '304502210088251984a09c72a887dd8337baee3f65b580ee4e78439fc88935775719cefc670220547dc87e5288edb27990b17f535f10642704e596ce0e50f0a2252cf58dfee275';
|
||
const algorithm = 'aes-192-cbc'; // cipher 和 key 的长度必须相同,例如 cipher 是 aes-192,那么 key 就必须是 192/8=24 字节 = 48 hex 的。
|
||
const key = Buffer.from('8c0ca36264f29389e87d983b269709a92c3455178b271ae0', 'hex')
|
||
let cipherECC = {}
|
||
let signature2 = ''
|
||
|
||
export default {
|
||
data() {
|
||
return {
|
||
title: 'uni-app 加密工具兼容性测试。红色按钮的还有问题'hex_to_buf
|
||
};
|
||
},
|
||
onLoad() { },
|
||
methods: {
|
||
randomBytes() {
|
||
try {
|
||
this.title = crypto.randomBytes(16).toString('hex');
|
||
} catch (exception) {
|
||
this.title = exception.toString();
|
||
}
|
||
},
|
||
scrypt() {
|
||
try {
|
||
this.title = crypto.scryptSync('用户定义的密码', '盐值', 24);
|
||
} catch (exception) {
|
||
this.title = exception.toString();
|
||
}
|
||
},
|
||
secureRandom() {
|
||
try {
|
||
this.title = secureRandom(16).toString();
|
||
} catch (exception) {
|
||
this.title = exception.toString();
|
||
}
|
||
},
|
||
generateMnemonic() {
|
||
try {
|
||
this.title = bip39.generateMnemonic();
|
||
} catch (exception) {
|
||
this.title = exception.toString();
|
||
}
|
||
},
|
||
mnemonic2seed() {
|
||
try {
|
||
bip39.setDefaultWordlist('chinese_simplified');
|
||
this.title = bip39.mnemonicToSeedSync('滴 民 延 腹 召 罩 巧 舟 小 顶 辩 资').toString('hex'); // 安卓和ios的微信浏览器,iOS app通过,安卓app失败
|
||
} catch (exception) {
|
||
this.title = exception.toString();
|
||
}
|
||
},
|
||
|
||
prikey2pubkey() {
|
||
try {
|
||
this.title = new crypto.createECDH('secp256k1').setPrivateKey(keypair.prikey, 'hex').getPublicKey('hex', 'compressed'); // 在ios和安卓 app里 setPrivateKey() 仍然报错: TypeError: null is not an object (evaluating 'this.rand.getBytes'),微信浏览器里倒成功了
|
||
// 另一种算法:this.title = secp256k1.publicKeyCreate(Buffer.from(keypair.prikey, 'hex'), true) // 全部通过
|
||
} catch (exception) {
|
||
this.title = exception.toString();
|
||
}
|
||
},
|
||
|
||
validateMnemonic() {
|
||
// iOS app 通过,安卓 app 失败,安卓版微信浏览器失败
|
||
try {
|
||
bip39.setDefaultWordlist('chinese_simplified');
|
||
this.title = '正确结果是 true,实际结果是:' + bip39.validateMnemonic('滴 民 延 腹 召 罩 巧 舟 小 顶 辩 资');
|
||
} catch (exception) {
|
||
this.title = exception.toString();
|
||
}
|
||
},
|
||
|
||
encrypt() {
|
||
try {
|
||
const iv = Buffer.alloc(16, 0); // 初始化向量。
|
||
const cipher = crypto.createCipheriv(algorithm, key, iv);
|
||
let encrypted = cipher.update('月落乌啼霜满天', 'utf8', 'hex');
|
||
encrypted += cipher.final('hex');
|
||
this.title = encrypted;
|
||
} catch (exception) {
|
||
this.title = exception.toString();
|
||
}
|
||
},
|
||
|
||
decrypt() {
|
||
try {
|
||
const iv = Buffer.alloc(16, 0); // 初始化向量。
|
||
const decipher = crypto.createDecipheriv(algorithm, key, iv);
|
||
// 使用相同的算法、密钥和 iv 进行加密。
|
||
const encrypted = "9ac679a1e7d9704df26e345fa91a8dc6feb3faa44fbf1821262a7d5910b76464";
|
||
let decrypted = decipher.update(encrypted, 'hex', 'utf8');
|
||
decrypted += decipher.final('utf8');
|
||
this.title = decrypted;
|
||
} catch (exception) {
|
||
this.title = exception.toString();
|
||
}
|
||
},
|
||
|
||
async sign() {
|
||
try {
|
||
this.title = await ticc.sign({ data: '月落乌啼霜满天', prikey: keypair.prikey })
|
||
signature2 = this.title
|
||
} catch (exception) {
|
||
this.title = exception.toString();
|
||
}
|
||
},
|
||
|
||
async verify() {
|
||
try {
|
||
this.title = await ticc.verify({ data: '月落乌啼霜满天', signature: signature2.toUpperCase(), pubkey: keypair.pubkey }) // 大小写不影响验签!
|
||
} catch (exception) {
|
||
this.title = exception.toString();
|
||
}
|
||
},
|
||
typedArray2Buffer(array) {
|
||
return array.buffer.slice(array.byteOffset, array.byteLength + array.byteOffset);
|
||
},
|
||
async encryptECC() {
|
||
try {
|
||
// let kp=eccrypto.generateKeyPair();
|
||
var privateKey = eccrypto.generatePrivate();
|
||
var publicKey = eccrypto.getPublic(privateKey);
|
||
let kp = { privateKey, publicKey }
|
||
console.log(kp)
|
||
let encrypted = await eccrypto.encrypt(Buffer.from(ticc.hex_to_buf(keypair.pubkey)), '月落乌啼霜满天')
|
||
cipherECC = encrypted
|
||
this.title = encrypted;
|
||
} catch (exception) {
|
||
this.title = exception.toString();
|
||
}
|
||
},
|
||
async decryptECC() {
|
||
try {
|
||
let plaindata = await eccrypto.decrypt(Buffer.from(keypair.prikey, 'hex'), cipherECC)
|
||
this.title = plaindata.toString()
|
||
} catch (exception) {
|
||
this.title = exception.toString();
|
||
}
|
||
},
|
||
|
||
async signECC() {
|
||
try {
|
||
let hashBuf = crypto
|
||
.createHash('sha256')
|
||
.update('月落乌啼霜满天')
|
||
.digest();
|
||
this.title = (await eccrypto.sign(Buffer.from(keypair.prikey, 'hex'), hashBuf)).toString('hex');
|
||
} catch (exception) {
|
||
this.title = exception.toString();
|
||
}
|
||
},
|
||
|
||
async verifyECC() {
|
||
try {
|
||
let hashBuf = crypto
|
||
.createHash('sha256')
|
||
.update('月落乌啼霜满天')
|
||
.digest();
|
||
if (null === (await eccrypto.verify(Buffer.from(keypair.pubkey, 'hex'), hashBuf, Buffer.from(signature, 'hex')))) {
|
||
this.title = true;
|
||
}
|
||
} catch (exception) {
|
||
this.title = exception.toString();
|
||
}
|
||
}
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<style>
|
||
.content {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.logo {
|
||
height: 200rpx;
|
||
width: 200rpx;
|
||
margin-top: 200rpx;
|
||
margin-left: auto;
|
||
margin-right: auto;
|
||
margin-bottom: 50rpx;
|
||
}
|
||
|
||
.text-area {
|
||
display: flex;
|
||
flex-flow: column;
|
||
justify-content: center;
|
||
}
|
||
|
||
.title {
|
||
font-size: 36rpx;
|
||
color: #8f8f94;
|
||
word-break: break-all;
|
||
}
|
||
|
||
button {
|
||
margin: 10rpx auto;
|
||
}
|
||
</style>
|