encrypt.vue 12.1 KB
Newer Older
B
baiy 已提交
1
<template>
B
baiy 已提交
2 3 4
    <heightResize ignore :append="['.page-option-block']" @resize="resize">
        <autoHeightTextarea v-model="current.input" :height="inputHeight" :placeholder="$t('encrypt_input')"/>
        <option-block class="page-option-block">
5 6 7
            <Form :model="formItem" label-position="top">
            <Form-item label="算法: ">
                <Select v-model="current.type">
B
baiy 已提交
8 9
                    <Option v-for="v in type" :value="v" :key="v">{{ v }}</Option>
                </Select>
10 11 12 13 14 15 16 17 18 19 20 21 22 23
            </Form-item>
            <Form-item label="密钥: ">
                <Select v-model="current.keyFormat">
                    <Option value="Hex">Hex</Option>
                    <Option value="Base64">Base64</Option>
                    <Option value="Password">Password</Option>
                </Select>
                <Input v-model="current.password" :placeholder="$t('encrypt_password')" type="textarea" :autosize="{minRows: 2, maxRows: 5}"></Input>
            </Form-item>
            <Form-item label="IV 向量(Hex 格式): ">
                <Input v-model="current.iv" :placeholder="$t('iv')" type="textarea" :autosize="{minRows: 3, maxRows: 5}"></Input>
            </Form-item>
            <Form-item label="加密模式: " v-if="current.type === 'SM2'">
                <Select v-model="current.sm2CipherMode">
B
baiy 已提交
24 25 26
                    <Option value="C1C3C2">C1C3C2</Option>
                    <Option value="C1C2C3">C1C2C3</Option>
                </Select>
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
            </Form-item>
            <Form-item label="加密模式: " v-else-if="current.type === 'SM4'">
                <Select v-model="current.mode">
                    <Option value="ecb">ECB</Option>
                    <Option value="cbc">CBC</Option>
                </Select>
                <Select v-model="current.padding">
                    <Option value="pkcs#7">Pkcs7</Option>
                    <Option value="none">NoPadding</Option>
                </Select>
            </Form-item>
            <Form-item label="加密模式: " v-else>
                <Select v-model="current.mode">
                    <Option value="ECB">ECB</Option>
                    <Option value="CBC">CBC</Option>
                    <Option value="CFB">CFB</Option>
                    <Option value="OFB">OFB</Option>
                    <Option value="CTR">CTR</Option>
                </Select>
                <Select v-model="current.padding">
                    <Option value="Pkcs7">Pkcs7</Option>
                    <Option value="Iso97971">Iso97971</Option>
                    <Option value="AnsiX923">AnsiX923</Option>
                    <Option value="Iso10126">Iso10126</Option>
                    <Option value="ZeroPadding">ZeroPadding</Option>
                    <Option value="NoPadding">NoPadding</Option>
                </Select>
            </Form-item>
            <Form-item>
B
baiy 已提交
56
                <ButtonGroup>
B
baiy 已提交
57 58 59 60 61
                    <Button type="primary" @click="handle('encrypt')">{{ $t('encrypt_encrypt') }}</Button>
                    <Button type="primary" @click="handle('decrypt')">{{ $t('encrypt_decrypt') }}</Button>
                    <Button type="primary" @click="sm2Generate()" v-if="current.type === 'SM2'">
                        {{ $t('encrypt_generate_secret_key') }}
                    </Button>
B
baiy 已提交
62
                </ButtonGroup>
63 64
            </Form-item>
            </Form>
B
baiy 已提交
65
        </option-block>
B
baiy 已提交
66 67
        <autoHeightTextarea :value="current.output" :height="outputHeight" :placeholder="$t('encrypt_output')"/>
    </heightResize>
B
baiy 已提交
68 69
</template>
<script>
B
baiy 已提交
70 71 72
import crypto from "crypto-js"
import heightResize from "./components/heightResize";
import autoHeightTextarea from "./components/autoHeightTextarea";
73
import { CryptoJS } from 'jsrsasign';
B
baiy 已提交
74 75 76 77 78 79 80 81 82 83 84 85

export default {
    components: {
        heightResize,
        autoHeightTextarea
    },
    created() {
        this.$initToolData('input')
    },
    methods: {
        handle(v) {
            const sm2 = require('sm-crypto').sm2
86
            const sm4 = require('sm-crypto').sm4
B
baiy 已提交
87 88 89
            if (this.current.input) {
                try {
                    let output = ""
B
baiy 已提交
90 91 92 93 94
                    switch (this.current.type) {
                        case "AES":
                        case "DES":
                        case "RC4":
                        case "Rabbit":
B
baiy 已提交
95
                        case "TripleDES":
B
baiy 已提交
96
                            if (v === "encrypt") {
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
                                if (this.current.keyFormat !== "Password") {
                                    output = crypto[this.current.type].encrypt(
                                        // todo 后续可以考虑支持原文输入的编码格式,以便应对一些二进制格式
                                        this.current.input,
                                        // 转换为 WordArray 形式作为密钥传入
                                        crypto.enc[this.current.keyFormat].parse(this.current.password),
                                        {
                                            // IV 要求为 Hex,按照 Hex 解析为 WordArray
                                            iv: crypto.enc.Hex.parse(this.current.iv),
                                            mode: crypto.mode[this.current.mode],
                                            padding: crypto.pad[this.current.padding]
                                        }
                                    ).ciphertext;
                                } else {
                                    // 兼容 crypto-js 的密码模式
                                    output = crypto[this.current.type].encrypt(this.current.input, this.current.password).toString();
                                }
B
baiy 已提交
114
                            } else {
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
                                if (this.current.keyFormat !== "Password") {
                                    // crypto-js 要求解密时传入为 CipherParams,使用 CipherText 构建 CipherParams
                                    let cipherData = CryptoJS.lib.CipherParams.create({
                                        ciphertext: crypto.enc.Hex.parse(this.current.input)
                                    });
                                    output = crypto[this.current.type].decrypt(
                                        cipherData, 
                                        // 转换为 WordArray 形式作为密钥传入
                                        crypto.enc[this.current.keyFormat].parse(this.current.password),
                                        {
                                            // IV 要求为 Hex,按照 Hex 解析为 WordArray
                                            iv: crypto.enc.Hex.parse(this.current.iv),
                                            mode: crypto.mode[this.current.mode],
                                            padding: crypto.pad[this.current.padding]
                                        }
                                    ).toString(crypto.enc.Utf8);
                                } else {
                                    // 兼容 crypto-js 的密码模式
                                    output = crypto[this.current.type].decrypt(this.current.input, this.current.password).toString(crypto.enc.Utf8);
                                }
B
baiy 已提交
135 136
                            }
                            break;
B
baiy 已提交
137 138
                        case "SM2":
                            if (v === "encrypt") {
B
baiy 已提交
139
                                output = sm2.doEncrypt(
B
baiy 已提交
140 141 142 143
                                    this.current.input,
                                    this.current.password,
                                    this.current.sm2CipherMode
                                );
B
baiy 已提交
144 145
                            } else {
                                output = sm2.doDecrypt(
146
                                    this.current.input,
B
baiy 已提交
147 148 149 150 151
                                    this.current.password,
                                    this.current.sm2CipherMode
                                );
                            }
                            break;
152
                        case "SM4":
153
                            // sm-crypto 要求传入的 key 为 Hex 格式,因此对于非 Hex 格式的数据进行转换
154
                            let sm4Key = this.current.password;
155
                            if (this.current.keyFormat === "Base64") {
156 157
                                sm4Key = crypto.enc.Hex.stringify(crypto.enc[this.current.keyFormat].parse(this.current.password));
                            } else if(this.current.keyFormat === "Password") {
158 159
                                // 如果是 Password,按照 Utf8 编码进行处理,转换为 Hex 格式
                                // 注意因为库的区别,password 模式跟 crypto-js 的处理不一样
160 161
                                sm4Key = crypto.enc.Hex.stringify(crypto.enc.Utf8.parse(this.current.password));
                            }
162

163
                            if(v === "encrypt") {
164 165 166 167 168 169
                                // SM4 加密
                                output = sm4.encrypt(
                                    this.current.input,
                                    sm4Key, 
                                    {
                                        mode: this.current.mode.toLowerCase(), 
170
                                        // sm-crypto 传入的 iv 为 Hex 格式
171 172 173 174
                                        iv: this.current.iv,
                                        padding: this.current.padding
                                    }
                                );
175
                            } else {
176 177 178 179 180 181
                                // SM4 解密
                                output = sm4.decrypt(
                                    this.current.input, 
                                    sm4Key,
                                    {
                                        mode: this.current.mode.toLowerCase(), 
182
                                        // sm-crypto 传入的 iv 为 Hex 格式
183 184 185 186
                                        iv: this.current.iv,
                                        padding: this.current.padding
                                    }
                                );
187
                            }
B
baiy 已提交
188
                    }
B
baiy 已提交
189 190 191 192 193 194 195 196
                    if (!output) {
                        throw new Error("output null")
                    }
                    this.current.output = output
                } catch (e) {
                    return this.$Message.error(
                        this.$t('encrypt_failed', [e.message]).toString()
                    )
B
baiy 已提交
197
                }
B
baiy 已提交
198 199 200 201
                this.current.operation = v;
                this.$clipboardCopy(this.current.output);
                this.$saveToolData(this.current);
            }
B
baiy 已提交
202
        },
B
baiy 已提交
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
        sm2Generate() {
            const sm2 = require('sm-crypto').sm2
            let keypair = sm2.generateKeyPairHex()
            let string = [
                this.$t('encrypt_public_key'),
                keypair.publicKey,
                this.$t('encrypt_private_key'),
                keypair.privateKey, '',
                this.$t('encrypt_secret_key_prompt')
            ].join("\n");
            this.$Modal.info({
                render: (h) => {
                    return h('Input', {
                        props: {
                            value: string,
                            type: "textarea",
                            rows: 9
                        }
                    })
B
baiy 已提交
222
                },
B
baiy 已提交
223 224 225
                okText: this.$t('encrypt_close'),
                width: 600
            })
B
baiy 已提交
226
        },
B
baiy 已提交
227 228 229 230 231 232 233 234 235 236
        resize(height) {
            this.inputHeight = Math.min(160, Math.ceil(height / 2))
            this.outputHeight = height - this.inputHeight
        }
    },
    data() {
        return {
            current: {
                input: "",
                password: "",
237 238 239 240
                keyFormat: "Hex",
                iv: "",
                mode:"ECB",
                padding:"Pkcs7",
B
baiy 已提交
241 242 243 244 245
                sm2CipherMode: "C1C3C2",
                output: "",
                type: "AES",
                operation: ""
            },
246
            type: ["AES", "DES", "RC4", "Rabbit", "TripleDES", "SM2", "SM4"],
B
baiy 已提交
247 248 249 250 251 252
            inputHeight: 100,
            outputHeight: 100
        }
    },
}
</script>