1- const forge = require ( ' node-forge' ) ;
2- const utils = require ( ' ../utils/utils' ) ;
1+ const forge = require ( " node-forge" ) ;
2+ const utils = require ( " ../utils/utils" ) ;
33const c = require ( "../utils/constants" ) ;
44
55/**
@@ -11,18 +11,25 @@ const c = require("../utils/constants");
1111 * @constructor
1212 */
1313function FieldLevelCrypto ( config ) {
14-
1514 isValidConfig . call ( this , config ) ;
1615
1716 // Load public certificate (for encryption)
18- this . encryptionCertificate = utils . readPublicCertificate ( config . encryptionCertificate ) ;
17+ this . encryptionCertificate = utils . readPublicCertificate (
18+ config . encryptionCertificate
19+ ) ;
1920
2021 // Load private key (for decryption)
2122 this . privateKey = utils . getPrivateKey ( config ) ;
2223
2324 this . encoding = config . dataEncoding ;
2425
25- this . publicKeyFingerprint = config . publicKeyFingerprint || utils . computePublicFingerprint ( config , this . encryptionCertificate , this . encoding ) ;
26+ this . publicKeyFingerprint =
27+ config . publicKeyFingerprint ||
28+ utils . computePublicFingerprint (
29+ config ,
30+ this . encryptionCertificate ,
31+ this . encoding
32+ ) ;
2633
2734 this . publicKeyFingerprintFieldName = config . publicKeyFingerprintFieldName ;
2835
@@ -51,24 +58,32 @@ function FieldLevelCrypto(config) {
5158 const enc = encryptionParams || this . newEncryptionParams ( options ) ;
5259
5360 // Create Cipher
54- const cipher = forge . cipher . createCipher ( ' AES-CBC' , enc . secretKey ) ;
61+ const cipher = forge . cipher . createCipher ( " AES-CBC" , enc . secretKey ) ;
5562
5663 // Encrypt payload
57- cipher . start ( { iv : enc . iv } ) ;
64+ cipher . start ( { iv : enc . iv } ) ;
5865 cipher . update ( forge . util . createBuffer ( data , c . UTF8 ) ) ;
5966 cipher . finish ( ) ;
6067 const encrypted = cipher . output . getBytes ( ) ;
6168
6269 const encryptedData = {
63- [ this . encryptedValueFieldName ] : utils . bytesToString ( encrypted , this . encoding ) ,
70+ [ this . encryptedValueFieldName ] : utils . bytesToString (
71+ encrypted ,
72+ this . encoding
73+ ) ,
6474 iv : utils . bytesToString ( enc . iv , this . encoding ) ,
65- [ this . encryptedKeyFieldName ] : utils . bytesToString ( enc . encryptedKey , this . encoding )
75+ [ this . encryptedKeyFieldName ] : utils . bytesToString (
76+ enc . encryptedKey ,
77+ this . encoding
78+ ) ,
6679 } ;
6780 if ( this . publicKeyFingerprint ) {
68- encryptedData [ this . publicKeyFingerprintFieldName ] = this . publicKeyFingerprint ;
81+ encryptedData [ this . publicKeyFingerprintFieldName ] =
82+ this . publicKeyFingerprint ;
6983 }
7084 if ( this . oaepHashingAlgorithmFieldName ) {
71- encryptedData [ this . oaepHashingAlgorithmFieldName ] = this . oaepHashingAlgorithm . replace ( "-" , "" ) ;
85+ encryptedData [ this . oaepHashingAlgorithmFieldName ] =
86+ this . oaepHashingAlgorithm . replace ( "-" , "" ) ;
7287 }
7388 return encryptedData ;
7489 } ;
@@ -83,16 +98,29 @@ function FieldLevelCrypto(config) {
8398 * @param encryptedKey Encrypted key
8499 * @returns {Object } Decrypted Json object
85100 */
86- this . decryptData = function ( encryptedData , iv , oaepHashingAlgorithm , encryptedKey ) {
87- const decryptedKey = this . privateKey . decrypt ( utils . stringToBytes ( encryptedKey , this . encoding ) , 'RSA-OAEP' ,
88- createOAEPOptions ( 'RSA-OAEP' , oaepHashingAlgorithm ) ) ;
101+ this . decryptData = function (
102+ encryptedData ,
103+ iv ,
104+ oaepHashingAlgorithm ,
105+ encryptedKey
106+ ) {
107+ const decryptedKey = this . privateKey . decrypt (
108+ utils . stringToBytes ( encryptedKey , this . encoding ) ,
109+ "RSA-OAEP" ,
110+ createOAEPOptions ( "RSA-OAEP" , oaepHashingAlgorithm )
111+ ) ;
89112
90113 // Init decipher
91- const decipher = forge . cipher . createDecipher ( ' AES-CBC' , decryptedKey ) ;
114+ const decipher = forge . cipher . createDecipher ( " AES-CBC" , decryptedKey ) ;
92115
93116 // Decrypt payload
94- decipher . start ( { iv : utils . stringToBytes ( iv , this . encoding ) } ) ;
95- decipher . update ( forge . util . createBuffer ( utils . stringToBytes ( encryptedData , this . encoding ) , c . BINARY ) ) ;
117+ decipher . start ( { iv : utils . stringToBytes ( iv , this . encoding ) } ) ;
118+ decipher . update (
119+ forge . util . createBuffer (
120+ utils . stringToBytes ( encryptedData , this . encoding ) ,
121+ c . BINARY
122+ )
123+ ) ;
96124 decipher . finish ( ) ;
97125
98126 try {
@@ -115,11 +143,15 @@ function FieldLevelCrypto(config) {
115143 const iv = options [ "iv" ] || forge . random . getBytesSync ( 16 ) ;
116144
117145 // Generate a secret key (should be 128 (or 256) bits)
118- const secretKey = options [ "secretKey" ] || generateSecretKey ( 'AES' , 128 , 'SHA-256' ) ;
146+ const secretKey =
147+ options [ "secretKey" ] || generateSecretKey ( "AES" , 128 , "SHA-256" ) ;
119148
120149 // Encrypt secret key with issuer key
121- const encryptedKey = this . encryptionCertificate . publicKey . encrypt ( secretKey ,
122- 'RSA-OAEP' , createOAEPOptions ( 'RSA-OAEP' , this . oaepHashingAlgorithm ) ) ;
150+ const encryptedKey = this . encryptionCertificate . publicKey . encrypt (
151+ secretKey ,
152+ "RSA-OAEP" ,
153+ createOAEPOptions ( "RSA-OAEP" , this . oaepHashingAlgorithm )
154+ ) ;
123155
124156 return {
125157 iv : iv ,
@@ -130,24 +162,23 @@ function FieldLevelCrypto(config) {
130162 encoded : {
131163 iv : utils . bytesToString ( iv , this . encoding ) ,
132164 secretKey : utils . bytesToString ( secretKey , this . encoding ) ,
133- encryptedKey : utils . bytesToString ( encryptedKey , this . encoding )
134- }
165+ encryptedKey : utils . bytesToString ( encryptedKey , this . encoding ) ,
166+ } ,
135167 } ;
136168 } ;
137-
138169}
139170
140171/**
141172 * @private
142173 */
143174function createOAEPOptions ( asymmetricCipher , oaepHashingAlgorithm ) {
144- if ( asymmetricCipher . includes ( ' OAEP' ) && oaepHashingAlgorithm !== null ) {
175+ if ( asymmetricCipher . includes ( " OAEP" ) && oaepHashingAlgorithm !== null ) {
145176 const mdForOaep = createMessageDigest ( oaepHashingAlgorithm ) ;
146177 return {
147178 md : mdForOaep ,
148179 mgf1 : {
149- md : mdForOaep
150- }
180+ md : mdForOaep ,
181+ } ,
151182 } ;
152183 }
153184}
@@ -157,27 +188,26 @@ function createOAEPOptions(asymmetricCipher, oaepHashingAlgorithm) {
157188 */
158189function createMessageDigest ( digest ) {
159190 switch ( digest . toUpperCase ( ) ) {
160- case ' SHA-256' :
161- case ' SHA256' :
191+ case " SHA-256" :
192+ case " SHA256" :
162193 return forge . md . sha256 . create ( ) ;
163- case ' SHA-512' :
164- case ' SHA512' :
194+ case " SHA-512" :
195+ case " SHA512" :
165196 return forge . md . sha512 . create ( ) ;
166197 }
167198}
168199
169-
170200/**
171201 * @private
172202 */
173203function generateSecretKey ( algorithm , size , digest ) {
174- if ( algorithm === ' AES' ) {
204+ if ( algorithm === " AES" ) {
175205 const key = forge . random . getBytesSync ( size / 8 ) ;
176206 const md = createMessageDigest ( digest ) ;
177207 md . update ( key ) ;
178208 return md . digest ( ) . getBytes ( 16 ) ;
179209 }
180- throw new Error ( ' Unsupported symmetric algorithm' ) ;
210+ throw new Error ( " Unsupported symmetric algorithm" ) ;
181211}
182212
183213/**
@@ -186,23 +216,40 @@ function generateSecretKey(algorithm, size, digest) {
186216 * @private
187217 */
188218function isValidConfig ( config ) {
189- const propertiesBasic = [ "oaepPaddingDigestAlgorithm" , "dataEncoding" , "encryptionCertificate" , "encryptedValueFieldName" ] ;
219+ const propertiesBasic = [
220+ "oaepPaddingDigestAlgorithm" ,
221+ "dataEncoding" ,
222+ "encryptionCertificate" ,
223+ "encryptedValueFieldName" ,
224+ ] ;
190225 const propertiesField = [ "ivFieldName" , "encryptedKeyFieldName" ] ;
191- const propertiesHeader = [ "ivHeaderName" , "encryptedKeyHeaderName" , "oaepHashingAlgorithmHeaderName" ] ;
226+ const propertiesHeader = [
227+ "ivHeaderName" ,
228+ "encryptedKeyHeaderName" ,
229+ "oaepHashingAlgorithmHeaderName" ,
230+ ] ;
192231 const contains = ( props ) => {
193232 return props . every ( ( elem ) => {
194233 return config [ elem ] !== null && typeof config [ elem ] !== "undefined" ;
195234 } ) ;
196235 } ;
197- if ( typeof config !== ' object' || config === null ) {
236+ if ( typeof config !== " object" || config === null ) {
198237 throw Error ( "Config not valid: config should be an object." ) ;
199238 }
200- if ( config [ "paths" ] === null || typeof config [ "paths" ] === "undefined" ||
201- ! ( config [ "paths" ] instanceof Array ) ) {
239+ if (
240+ config [ "paths" ] === null ||
241+ typeof config [ "paths" ] === "undefined" ||
242+ ! ( config [ "paths" ] instanceof Array )
243+ ) {
202244 throw Error ( "Config not valid: paths should be an array of path element." ) ;
203245 }
204- if ( ! contains ( propertiesBasic ) || ( ! contains ( propertiesField ) && ! contains ( propertiesHeader ) ) ) {
205- throw Error ( "Config not valid: please check that all the properties are defined." ) ;
246+ if (
247+ ! contains ( propertiesBasic ) ||
248+ ( ! contains ( propertiesField ) && ! contains ( propertiesHeader ) )
249+ ) {
250+ throw Error (
251+ "Config not valid: please check that all the properties are defined."
252+ ) ;
206253 }
207254 if ( config [ "paths" ] . length === 0 ) {
208255 throw Error ( "Config not valid: paths should be not empty." ) ;
@@ -215,25 +262,39 @@ function isValidConfig(config) {
215262}
216263
217264function validateFingerprint ( config , contains ) {
218- const propertiesFingerprint = [ "publicKeyFingerprintType" , "publicKeyFingerprintFieldName" , "publicKeyFingerprintHeaderName" ] ;
265+ const propertiesFingerprint = [
266+ "publicKeyFingerprintType" ,
267+ "publicKeyFingerprintFieldName" ,
268+ "publicKeyFingerprintHeaderName" ,
269+ ] ;
219270 const propertiesOptionalFingerprint = [ "publicKeyFingerprint" ] ;
220- if ( ! contains ( propertiesOptionalFingerprint )
221- && ( config [ propertiesFingerprint [ 1 ] ] || config [ propertiesFingerprint [ 2 ] ] )
222- && config [ propertiesFingerprint [ 0 ] ] !== "certificate" && config [ propertiesFingerprint [ 0 ] ] !== "publicKey" ) {
223- throw Error ( "Config not valid: propertiesFingerprint should be: 'certificate' or 'publicKey'" ) ;
271+ if (
272+ ! contains ( propertiesOptionalFingerprint ) &&
273+ ( config [ propertiesFingerprint [ 1 ] ] || config [ propertiesFingerprint [ 2 ] ] ) &&
274+ config [ propertiesFingerprint [ 0 ] ] !== "certificate" &&
275+ config [ propertiesFingerprint [ 0 ] ] !== "publicKey"
276+ ) {
277+ throw Error (
278+ "Config not valid: propertiesFingerprint should be: 'certificate' or 'publicKey'"
279+ ) ;
224280 }
225281}
226282
227283function validateRootMapping ( config ) {
228284 function multipleRoots ( elem ) {
229- return elem . length !== 1 && elem . some ( ( item ) => {
230- return item . obj === "$" || item . element === "$" ;
231- } ) ;
285+ return (
286+ elem . length !== 1 &&
287+ elem . some ( ( item ) => {
288+ return item . obj === "$" || item . element === "$" ;
289+ } )
290+ ) ;
232291 }
233292
234293 config . paths . forEach ( ( path ) => {
235294 if ( multipleRoots ( path . toEncrypt ) || multipleRoots ( path . toDecrypt ) ) {
236- throw Error ( "Config not valid: found multiple configurations encrypt/decrypt with root mapping" ) ;
295+ throw Error (
296+ "Config not valid: found multiple configurations encrypt/decrypt with root mapping"
297+ ) ;
237298 }
238299 } ) ;
239300}
0 commit comments