import { Buffer } from '@stacks/common' ; import { CipherTextEncoding , SignedCipherObject , encryptECIES , decryptECIES , signECDSA , } from './ec' ; import { getPublicKeyFromPrivate } from './keys' ; export interface EncryptionOptions { default sign ? : boolean | string ; /**
     * String encoding format for the cipherText buffer.
     * Currently defaults to 'hex' for legacy backwards-compatibility.
     * Only used if the `encrypt` option is also used.
     * Note: in the future this should default to 'base64' for the significant
     * file size reduction.
     */ cipherTextEncoding ? : CipherTextEncoding ; /**
     * Specifies if the original unencrypted content is a ASCII or UTF-8 string.
     * For example stringified JSON.
     * If true, then when the ciphertext is decrypted, it will be returned as
     * a `string` type variable, otherwise will be returned as a Buffer.
     */ wasString ? : boolean ; } /**
 * Specify encryption options, and whether to sign the ciphertext.
 */ export interface EncryptContentOptions extends EncryptionOptions { /**
     * Encrypt the data with this key.
     */ publicKey ? : string ; /**
     * Encrypt the data with the public key corresponding to the supplied private key
     */ privateKey ? : string ; } param { String | Buffer } content param options param { String } options . publicKey return { String } export async function encryptContent ( content , options ? ) { const opts = Object . assign ( { } , options ) ; let privateKey ; if ( ! opts . publicKey ) { if ( ! opts . privateKey ) { throw new Error ( 'Either public key or private key must be supplied for encryption.' ) ; } opts . publicKey = getPublicKeyFromPrivate ( opts . privateKey ) ; } let wasString ; if ( typeof opts . wasString === 'boolean' ) { wasString = opts . wasString ; } else { wasString = typeof content === 'string' ; } const contentBuffer = typeof content === 'string' ? Buffer . from ( content ) : content ; const cipherObject = await encryptECIES ( opts . publicKey , contentBuffer , wasString , opts . cipherTextEncoding ) ; let cipherPayload = JSON . stringify ( cipherObject ) ; if ( opts . sign ) { if ( typeof opts . sign === 'string' ) { privateKey = opts . sign ; } else if ( ! privateKey ) { privateKey = opts . privateKey ; } const signatureObject = signECDSA ( privateKey ! , cipherPayload ) ; const signedCipherObject = { signature : signatureObject . signature , publicKey : signatureObject . publicKey , cipherText : cipherPayload , } ; cipherPayload = JSON . stringify ( signedCipherObject ) ; } return cipherPayload ; } param { String | Buffer } content param options param { String } options . privateKey return { String | Buffer } export function decryptContent ( content , options ? ) { const opts = Object . assign ( { } , options ) ; if ( ! opts . privateKey ) { throw new Error ( 'Private key is required for decryption.' ) ; } try { const cipherObject = JSON . parse ( content ) ; return decryptECIES ( opts . privateKey , cipherObject ) ; } catch ( err ) { if ( err instanceof SyntaxError ) { throw new Error ( 'Failed to parse encrypted content JSON. The content may not ' + 'be encrypted. If using getFile, try passing { decrypt: false }.' ) ; } else { throw err ; } } }