|
| 1 | +<script setup lang="ts"> |
| 2 | +import sshpk from 'sshpk'; |
| 3 | +import { computedCatch } from '@/composable/computed/catchedComputed'; |
| 4 | +import TextareaCopyable from '@/components/TextareaCopyable.vue'; |
| 5 | +
|
| 6 | +const hashTypes = [ |
| 7 | + 'sha1', 'sha256', 'sha384', 'sha512', 'md5', |
| 8 | +]; |
| 9 | +
|
| 10 | +const verifyText = ref(''); |
| 11 | +const verifySignature = ref(''); |
| 12 | +const verifyPublicKey = ref(''); |
| 13 | +const [verifyOutput, verifyError] = computedCatch(() => { |
| 14 | + const publicKey = sshpk.parseKey(verifyPublicKey.value, 'auto'); |
| 15 | +
|
| 16 | + const v = publicKey.createVerify(); |
| 17 | + v.update(verifyText.value); |
| 18 | + return v.verify(verifySignature.value); |
| 19 | +}, { |
| 20 | + defaultValue: '', |
| 21 | + defaultErrorMessage: 'Unable to verify your text', |
| 22 | +}); |
| 23 | +
|
| 24 | +const signText = ref(''); |
| 25 | +const signPrivateKey = ref(''); |
| 26 | +const signPrivateKeyPassphrase = ref(''); |
| 27 | +const signHashType = ref('sha1'); |
| 28 | +const [signOutput, signError] = computedCatch(() => { |
| 29 | + const privateKey = sshpk.parsePrivateKey(signPrivateKey.value, 'auto', { passphrase: signPrivateKeyPassphrase.value }); |
| 30 | + const s = privateKey.createSign(signHashType.value as sshpk.AlgorithmHashType); |
| 31 | + s.update(signText.value); |
| 32 | + const signature = s.sign(); |
| 33 | + return { |
| 34 | + asn1: signature.toString('asn1'), |
| 35 | + ssh: signature.toString('ssh'), |
| 36 | + }; |
| 37 | +}, { |
| 38 | + defaultValue: { |
| 39 | + asn1: '', |
| 40 | + ssh: '', |
| 41 | + }, |
| 42 | + defaultErrorMessage: 'Unable to sign your text', |
| 43 | +}); |
| 44 | +</script> |
| 45 | + |
| 46 | +<template> |
| 47 | + <div> |
| 48 | + <c-card title="Sign"> |
| 49 | + <div> |
| 50 | + <c-input-text |
| 51 | + v-model:value="signText" |
| 52 | + label="Your text:" |
| 53 | + placeholder="The string to sign" |
| 54 | + rows="4" |
| 55 | + multiline raw-text monospace autosize flex-1 |
| 56 | + /> |
| 57 | + <c-select |
| 58 | + v-model:value="signHashType" |
| 59 | + label="Hash Type:" |
| 60 | + :options="hashTypes" |
| 61 | + placeholder="Select the hashing algorithm" |
| 62 | + /> |
| 63 | + <div flex flex-1 flex-col gap-2> |
| 64 | + <c-input-text |
| 65 | + v-model:value="signPrivateKey" |
| 66 | + label="Your private key:" |
| 67 | + placeholder="The private key to use to sign message" |
| 68 | + rows="5" |
| 69 | + multiline raw-text monospace autosize flex-1 |
| 70 | + /> |
| 71 | + |
| 72 | + <c-input-text |
| 73 | + v-model:value="signPrivateKeyPassphrase" |
| 74 | + label="Your private key password:" clearable raw-text |
| 75 | + /> |
| 76 | + </div> |
| 77 | + </div> |
| 78 | + |
| 79 | + <c-alert v-if="signError && signPrivateKey !== ''" type="error" mt-12 title="Error while signing"> |
| 80 | + {{ signError }} |
| 81 | + </c-alert> |
| 82 | + |
| 83 | + <n-form-item label="ASN1 Signature:" mt-3> |
| 84 | + <TextareaCopyable |
| 85 | + :value="signOutput?.asn1 || ''" |
| 86 | + placeholder="ASN1 Signature" |
| 87 | + multiline monospace readonly autosize mt-5 |
| 88 | + /> |
| 89 | + </n-form-item> |
| 90 | + <n-form-item label="SSH Signature:" mt-3> |
| 91 | + <TextareaCopyable |
| 92 | + :value="signOutput?.ssh || ''" |
| 93 | + placeholder="SSG Signature" |
| 94 | + multiline monospace readonly autosize mt-5 |
| 95 | + /> |
| 96 | + </n-form-item> |
| 97 | + </c-card> |
| 98 | + |
| 99 | + <c-card title="Verify"> |
| 100 | + <div> |
| 101 | + <c-input-text |
| 102 | + v-model:value="verifyText" |
| 103 | + label="Your text to verify:" |
| 104 | + placeholder="The string to verify" |
| 105 | + rows="4" |
| 106 | + multiline raw-text monospace autosize flex-1 |
| 107 | + /> |
| 108 | + |
| 109 | + <c-input-text |
| 110 | + v-model:value="verifySignature" |
| 111 | + label="Associated signature:" |
| 112 | + placeholder="Text signature" |
| 113 | + rows="4" |
| 114 | + multiline raw-text monospace autosize flex-1 |
| 115 | + /> |
| 116 | + |
| 117 | + <div flex flex-1 flex-col gap-2> |
| 118 | + <c-input-text |
| 119 | + v-model:value="verifyPublicKey" |
| 120 | + label="Public key:" |
| 121 | + placeholder="Public key" |
| 122 | + rows="5" |
| 123 | + multiline raw-text monospace autosize flex-1 |
| 124 | + /> |
| 125 | + </div> |
| 126 | + </div> |
| 127 | + |
| 128 | + <c-alert v-if="verifyError && verifyPublicKey !== ''" type="error" mt-12 title="Error while verifying"> |
| 129 | + {{ verifyError }} |
| 130 | + </c-alert> |
| 131 | + <c-alert v-if="verifyOutput && verifyPublicKey !== ''" type="error" mt-12 title="Signature failed"> |
| 132 | + Signature is NOT valid for the given text |
| 133 | + </c-alert> |
| 134 | + <n-alert v-if="!verifyOutput && verifyPublicKey !== ''" type="success" mt-12 title="Signature verified"> |
| 135 | + Signature is valid for the given text |
| 136 | + </n-alert> |
| 137 | + </c-card> |
| 138 | + </div> |
| 139 | +</template> |
0 commit comments