<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>
