@@ -24,7 +24,7 @@ import {
2424 NexoDerivedKey ,
2525 SaleToPOISecuredMessage ,
2626 SecurityTrailer ,
27- } from "../typings/terminal /models" ;
27+ } from "../typings/cloudDevice /models" ;
2828import { EncryptionCredentialDetails } from "./encryptionCredentialDetails" ;
2929import InvalidSecurityKeyException from "./exception/invalidSecurityKeyException" ;
3030import NexoDerivedKeyGenerator from "./nexoDerivedKeyGenerator" ;
@@ -45,43 +45,54 @@ enum Modes {
4545 * - Constructs and validates {@link SecurityTrailer}
4646 */
4747class NexoSecurityManager {
48+
4849 /**
4950 * Encrypts a SaleToPOI message.
5051 *
5152 * @param messageHeader - The Nexo message header
5253 * @param saleToPoiMessageJson - The message body in JSON string format
5354 * @param credentials - The encryption credentials
54- * @returns A secured SaleToPOI message with encrypted payload and security trailer
55+ * @returns A instance of SaleToPOISecuredMessage with MessageHeader, NexoBlob (the encrypted payload) and SecurityTrailer
5556 */
5657 public static encrypt (
5758 messageHeader : MessageHeader ,
5859 saleToPoiMessageJson : string ,
5960 credentials : EncryptionCredentialDetails ,
6061 ) : SaleToPOISecuredMessage {
61- const derivedKey : NexoDerivedKey = NexoDerivedKeyGenerator . deriveKeyMaterial ( credentials . Passphrase ) ;
62- const saleToPoiMessageByteArray = Buffer . from ( saleToPoiMessageJson , "utf-8" ) ;
63- const ivNonce = NexoSecurityManager . generateRandomIvNonce ( ) ;
64- const encryptedSaleToPoiMessage = NexoSecurityManager . crypt (
65- saleToPoiMessageByteArray ,
66- derivedKey ,
67- ivNonce ,
68- Modes . ENCRYPT ,
69- ) ;
70- const encryptedSaleToPoiMessageHmac = NexoSecurityManager . hmac ( saleToPoiMessageByteArray , derivedKey ) ;
71-
72- const securityTrailer : SecurityTrailer = {
73- AdyenCryptoVersion : credentials . AdyenCryptoVersion ,
74- Hmac : encryptedSaleToPoiMessageHmac . toString ( "base64" ) ,
75- KeyIdentifier : credentials . KeyIdentifier ,
76- KeyVersion : credentials . KeyVersion ,
77- Nonce : ivNonce . toString ( "base64" ) ,
78- } ;
79-
80- return {
81- MessageHeader : messageHeader ,
82- NexoBlob : encryptedSaleToPoiMessage . toString ( "base64" ) ,
83- SecurityTrailer : securityTrailer ,
84- } ;
62+
63+ try {
64+
65+ const derivedKey : NexoDerivedKey = NexoDerivedKeyGenerator . deriveKeyMaterial ( credentials . Passphrase ) ;
66+ const saleToPoiMessageByteArray = Buffer . from ( saleToPoiMessageJson , "utf-8" ) ;
67+ const ivNonce = NexoSecurityManager . generateRandomIvNonce ( ) ;
68+ const encryptedSaleToPoiMessage = NexoSecurityManager . crypt (
69+ saleToPoiMessageByteArray ,
70+ derivedKey ,
71+ ivNonce ,
72+ Modes . ENCRYPT ,
73+ ) ;
74+ const encryptedSaleToPoiMessageHmac = NexoSecurityManager . hmac ( saleToPoiMessageByteArray , derivedKey ) ;
75+
76+ const securityTrailer : SecurityTrailer = {
77+ AdyenCryptoVersion : credentials . AdyenCryptoVersion ,
78+ Hmac : encryptedSaleToPoiMessageHmac . toString ( "base64" ) ,
79+ KeyIdentifier : credentials . KeyIdentifier ,
80+ KeyVersion : credentials . KeyVersion ,
81+ Nonce : ivNonce . toString ( "base64" ) ,
82+ } ;
83+
84+ return {
85+ MessageHeader : messageHeader ,
86+ NexoBlob : encryptedSaleToPoiMessage . toString ( "base64" ) ,
87+ SecurityTrailer : securityTrailer ,
88+ } ;
89+
90+ } catch ( err : any ) {
91+ // an error has occurred
92+ console . error ( err ) ;
93+ throw new NexoCryptoException ( err ?. message || "Unknown error during encryption" ) ;
94+ }
95+
8596 }
8697
8798 /**
@@ -90,29 +101,40 @@ class NexoSecurityManager {
90101 * @param saleToPoiSecureMessage - The secured message to decrypt
91102 * @param credentials - The encryption credentials
92103 * @throws {InvalidSecurityKeyException } If the credentials are invalid
93- * @throws {NexoCryptoException } If HMAC validation fails
104+ * @throws {NexoCryptoException } When an error occurs
94105 * @returns The decrypted SaleToPOI message as a UTF-8 string
95106 */
96107 public static decrypt (
97108 saleToPoiSecureMessage : SaleToPOISecuredMessage ,
98109 credentials : EncryptionCredentialDetails ,
99110 ) : string {
100- NexoSecurityManager . validateEncryptionCredentials ( credentials ) ;
101-
102- const encryptedSaleToPoiMessageByteArray = Buffer . from ( saleToPoiSecureMessage . NexoBlob , "base64" ) ;
103- const derivedKey = NexoDerivedKeyGenerator . deriveKeyMaterial ( credentials . Passphrase ) ;
104- const ivNonce = Buffer . from ( saleToPoiSecureMessage . SecurityTrailer . Nonce , "base64" ) ;
105- const decryptedSaleToPoiMessageByteArray = NexoSecurityManager . crypt (
106- encryptedSaleToPoiMessageByteArray ,
107- derivedKey ,
108- ivNonce ,
109- Modes . DECRYPT ,
110- ) ;
111-
112- const receivedHmac = Buffer . from ( saleToPoiSecureMessage . SecurityTrailer . Hmac , "base64" ) ;
113- NexoSecurityManager . validateHmac ( receivedHmac , decryptedSaleToPoiMessageByteArray , derivedKey ) ;
114-
115- return decryptedSaleToPoiMessageByteArray . toString ( "utf-8" ) ;
111+
112+ try {
113+ NexoSecurityManager . validateEncryptionCredentials ( credentials ) ;
114+
115+ // decrypt content of NexoBlob
116+ const encryptedSaleToPoiMessageByteArray = Buffer . from ( saleToPoiSecureMessage . NexoBlob , "base64" ) ;
117+
118+ const derivedKey = NexoDerivedKeyGenerator . deriveKeyMaterial ( credentials . Passphrase ) ;
119+ const ivNonce = Buffer . from ( saleToPoiSecureMessage . SecurityTrailer . Nonce , "base64" ) ;
120+ const decryptedSaleToPoiMessageByteArray = NexoSecurityManager . crypt (
121+ encryptedSaleToPoiMessageByteArray ,
122+ derivedKey ,
123+ ivNonce ,
124+ Modes . DECRYPT ,
125+ ) ;
126+
127+ const receivedHmac = Buffer . from ( saleToPoiSecureMessage . SecurityTrailer . Hmac , "base64" ) ;
128+ NexoSecurityManager . validateHmac ( receivedHmac , decryptedSaleToPoiMessageByteArray , derivedKey ) ;
129+
130+ return decryptedSaleToPoiMessageByteArray . toString ( "utf-8" ) ;
131+
132+ } catch ( err : any ) {
133+ // an error has occurred
134+ console . error ( err ) ;
135+ throw new NexoCryptoException ( err ?. message || "Unknown error during decryption" ) ;
136+ }
137+
116138 }
117139
118140 private static validateEncryptionCredentials ( credentials : EncryptionCredentialDetails ) : void {
@@ -127,19 +149,36 @@ class NexoSecurityManager {
127149 }
128150 }
129151
152+ /**
153+ * Performs AES-256-CBC encryption or decryption.
154+ *
155+ * @param bytes The data to be encrypted or decrypted.
156+ * @param dk The derived key containing the cipher key and IV.
157+ * @param ivNonce The random nonce to be XORed with the IV.
158+ * @param mode The operation mode (ENCRYPT or DECRYPT).
159+ * @throws {NexoCryptoException } If an error occurs during the cryptographic operation.
160+ * @returns The resulting encrypted or decrypted data as a Buffer.
161+ */
130162 private static crypt ( bytes : Buffer , dk : NexoDerivedKey , ivNonce : Buffer , mode : Modes ) : Buffer {
131- const actualIV = Buffer . alloc ( NexoEnum . IV_LENGTH ) ;
132- for ( let i = 0 ; i < NexoEnum . IV_LENGTH ; i ++ ) {
133- actualIV [ i ] = dk . iv [ i ] ^ ivNonce [ i ] ;
163+ try {
164+ const actualIV = Buffer . alloc ( NexoEnum . IV_LENGTH ) ;
165+ for ( let i = 0 ; i < NexoEnum . IV_LENGTH ; i ++ ) {
166+ actualIV [ i ] = dk . iv [ i ] ^ ivNonce [ i ] ;
167+ }
168+
169+ const cipher = mode === Modes . ENCRYPT
170+ ? createCipheriv ( "aes-256-cbc" , dk . cipherKey , actualIV )
171+ : createDecipheriv ( "aes-256-cbc" , dk . cipherKey , actualIV ) ;
172+
173+ let encrypted = ( cipher as Cipher ) . update ( bytes ) ;
174+ encrypted = Buffer . concat ( [ encrypted , cipher . final ( ) ] ) ;
175+ return encrypted ;
176+
177+ } catch ( err : any ) {
178+ // an error has occurred
179+ console . error ( err ) ;
180+ throw new NexoCryptoException ( err ?. message || "Unknown error during AES encryption or decryption" ) ;
134181 }
135-
136- const cipher = mode === Modes . ENCRYPT
137- ? createCipheriv ( "aes-256-cbc" , dk . cipherKey , actualIV )
138- : createDecipheriv ( "aes-256-cbc" , dk . cipherKey , actualIV ) ;
139-
140- let encrypted = ( cipher as Cipher ) . update ( bytes ) ;
141- encrypted = Buffer . concat ( [ encrypted , cipher . final ( ) ] ) ;
142- return encrypted ;
143182 }
144183
145184 private static hmac ( bytes : Buffer , derivedKey : NexoDerivedKey ) : Buffer {
0 commit comments