import { randomBytes } from 'crypto' ; import { decompressPublicKey } from './dataEncryptionKey' ; import { AES128DecryptAndHMAC , AES128EncryptAndHMAC , Decrypt as ECIESDecrypt , Encrypt as ECIESEncrypt , } from './ecies' ; const ECIES_SESSION_KEY_LEN = 129 ; const MIN_COMMENT_KEY_LENGTH = 33 ; const TAG = 'CommentEncryption' ; export interface EncryptionStatus { success : boolean ; comment : string ; } param { Buffer } data param { Buffer } pubKeyRecipient param { Buffer } pubKeySelf returns { Buffer } export function encryptData ( data , pubKeyRecipient , pubKeySelf ) { const sessionKey = randomBytes ( 16 ) ; const sessionKeyToSelf = ECIESEncrypt ( pubKeySelf , sessionKey ) ; const sessionKeyToOther = ECIESEncrypt ( pubKeyRecipient , sessionKey ) ; const ciphertext = AES128EncryptAndHMAC ( sessionKey , sessionKey , data ) ; return Buffer . concat ( [ sessionKeyToOther , sessionKeyToSelf , ciphertext ] ) ; } param { Buffer } data param { Buffer } key param { boolean } sender returns { Buffer } export function decryptData ( data , key , sender ) { if ( data . length < ECIES_SESSION_KEY_LEN * 2 + 48 ) { throw new Error ( 'Buffer length too short' ) ; } const sessionKeyEncrypted = sender ? data . slice ( ECIES_SESSION_KEY_LEN , ECIES_SESSION_KEY_LEN * 2 ) : data . slice ( 0 , ECIES_SESSION_KEY_LEN ) ; const sessionKey = ECIESDecrypt ( key , sessionKeyEncrypted ) ; const encryptedMessage = data . slice ( ECIES_SESSION_KEY_LEN * 2 ) ; return AES128DecryptAndHMAC ( sessionKey , sessionKey , encryptedMessage ) ; } param { string } comment param { Buffer } pubKeyRecipient param { Buffer } pubKeySelf returns { string } export function encryptComment ( comment , pubKeyRecipient , pubKeySelf ) { try { if ( pubKeyRecipient . length < MIN_COMMENT_KEY_LENGTH || pubKeySelf . length < MIN_COMMENT_KEY_LENGTH ) { throw new Error ( 'Comment key too short' ) ; } const pubRecip = decompressPublicKey ( pubKeyRecipient ) ; const pubSelf = decompressPublicKey ( pubKeySelf ) ; const data = encryptData ( Buffer . from ( comment , 'ucs2' ) , pubRecip , pubSelf ) . toString ( 'base64' ) ; return { success : true , comment : data } ; } catch ( e ) { console . info ( `${ TAG }/Error encrypting comment: ${ e }` ) ; return { success : false , comment } ; } } param { string } comment param { Buffer } key param { boolean } sender returns { string } export function decryptComment ( comment , key , sender ) { try { const buf = Buffer . from ( comment , 'base64' ) ; const data = decryptData ( buf , key , sender ) . toString ( 'ucs2' ) ; return { success : true , comment : data } ; } catch ( error ) { console . info ( `${ TAG }/Could not decrypt: ${ error . message }` ) ; return { success : false , comment } ; } } export const CommentEncryptionUtils = { encryptComment , decryptComment } ;