Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | 104x 1x 1x 1x 1x 1x 1x 1x 1x 8x 8x 1x 8x 1x 6x 6x 6x 6x 1x 2x 2x 1x 2x 2x 2x 2x 1x 3x 3x 3x 3x 3x 3x 3x 3x 2x 2x 2x 2x 2x 2x | import { Bytes, Checksum256, Checksum512, PrivateKey, PublicKey, Serializer, Struct, UInt32, UInt64, } from '@wharfkit/antelope' import {AES_CBC} from '@greymass/miniaes' @Struct.type('sealed_message') export class SealedMessage extends Struct { @Struct.field('public_key') from!: PublicKey @Struct.field('uint64') nonce!: UInt64 @Struct.field('bytes') ciphertext!: Bytes @Struct.field('uint32') checksum!: UInt32 } export function createSymmetricKey(secret: Checksum512, nonce: UInt64): Uint8Array { const key = Checksum512.hash(Serializer.encode({object: nonce}).appending(secret.array)) return key.array.slice(0, 32) } export function createIV(nonce: UInt64, secret: Checksum512): Checksum512 { return Checksum512.hash(Serializer.encode({object: nonce}).appending(secret.array)) } export function encryptMessage(iv: Checksum512, symmetricKey: Uint8Array, message: string): Bytes { const plaintext = Bytes.from(message, 'utf8').array const ivBytes = iv.array.slice(32, 48) const encrypted = AES_CBC.encrypt(plaintext, symmetricKey, true, ivBytes) return Bytes.from(encrypted) } export function decryptMessage( iv: Checksum512, symmetricKey: Uint8Array, message: Bytes ): Uint8Array { const ivBytes = iv.array.slice(32, 48) return AES_CBC.decrypt(message.array, symmetricKey, true, ivBytes) } /** * Seals a message using AES encryption and a shared secret derived from given keys. * @param message - The message to seal * @param privateKey - The private key to use for encryption * @param publicKey - The public key to use for encryption * @param nonce - A nonce to use for encryption * @returns The sealed message as Bytes */ export function sealMessage( message: string, privateKey: PrivateKey, publicKey: PublicKey, nonce: UInt64 ): Bytes { const secret = privateKey.sharedSecret(publicKey, {legacy: true}) const iv = createIV(nonce, secret) const symmetricKey = createSymmetricKey(secret, nonce) return encryptMessage(iv, symmetricKey, message) } export function sealedMessagePayload( message: string, privateKey: PrivateKey, publicKey: PublicKey, nonce?: UInt64 ): SealedMessage { Iif (!nonce) { nonce = UInt64.random() } const secret = privateKey.sharedSecret(publicKey, {legacy: true}) const iv = createIV(nonce, secret) const symmetricKey = createSymmetricKey(secret, nonce) const ciphertext = encryptMessage(iv, symmetricKey, message) const checksumView = new DataView(Checksum256.hash(iv.array).array.buffer) const checksum = checksumView.getUint32(0, true) return new SealedMessage({ from: privateKey.toPublic(), nonce, ciphertext, checksum, }) } /** * Decrypt a message using AES and shared secret derived from given keys. * @param message - The encrypted message bytes to decrypt * @param privateKey - The private key to use for deriving the shared secret * @param publicKey - The public key to use for deriving the shared secret * @param nonce - The nonce used in the encryption process * @returns The decrypted message as a UTF-8 string * @internal */ export function unsealMessage( message: Bytes, privateKey: PrivateKey, publicKey: PublicKey, nonce: UInt64 ): string { const secret = privateKey.sharedSecret(publicKey, {legacy: true}) const iv = createIV(nonce, secret) const symmetricKey = createSymmetricKey(secret, nonce) const decryptedMessage = decryptMessage(iv, symmetricKey, message) return Bytes.from(decryptedMessage).toString('utf8') } |