From b71c1f0bb898efd4e97a8a966d19993aa13dd2cf Mon Sep 17 00:00:00 2001 From: Sebastian-Dieguez Date: Tue, 4 Jun 2024 17:34:53 -0300 Subject: [PATCH 1/2] .NET interoperability for X509Certificate2 --- CHANGELOG.md | 27 +++++++++ lib/oids.js | 4 ++ lib/pbe.js | 155 +++++++++++++++++++++++++++++++++++++++++++++++++- lib/pkcs12.js | 62 +++++++++++++------- lib/x509.js | 34 +++++++++++ 5 files changed, 260 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 27d0e3a00..7cca555a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,33 @@ Forge ChangeLog =============== +## 1.3.2 - 2024-06-04 + +### Enhancement and interoperability +- **At [pkcs12.js] and [pbe.js].** + - Added (options.encryptCert) flag to allow encrypt [PKCS#7 ContentInfo], used in [PKCS#12 toPkcs12Asn1]. + - This ensures interoperability with [System.Security.Cryptography.X509Certificates.X509Certificate2(cert, password)]. + - Added suport for .NET interoperability for X509Certificate2(cert, password = "") + for do this set toPkcs12Asn1 with password = undefined. +### Completing OIDs +- **At [oids.js] and [x509.js].** + - Was added this: **'ocsp','caIssuers'** OIDs. + - Added setExtensions for this OIDs: 'ocsp','caIssuers'. + ```js + //Example of use: + { + name: 'authorityInfoAccess', //OCSP is Implemented in Fork https://github.com/SevanMelemedjian/forge.git + accessDescriptions: [ + { + accessMethod: 'ocsp', + accessLocation: 'http://yoursite.com/static/ocsp' + },{ + accessMethod: 'caIssuers', + accessLocation: 'http://yoursite.com/static/root.crt' + }] + } + ``` + ## 1.3.1 - 2022-03-29 ### Fixes diff --git a/lib/oids.js b/lib/oids.js index d1504eb16..9637beaf7 100644 --- a/lib/oids.js +++ b/lib/oids.js @@ -177,3 +177,7 @@ _IN('1.3.6.1.5.5.7.3.2', 'clientAuth'); _IN('1.3.6.1.5.5.7.3.3', 'codeSigning'); _IN('1.3.6.1.5.5.7.3.4', 'emailProtection'); _IN('1.3.6.1.5.5.7.3.8', 'timeStamping'); + +// authorityInfoAccess methods OIDs +_IN('1.3.6.1.5.5.7.48.1', 'ocsp'); +_IN('1.3.6.1.5.5.7.48.2', 'caIssuers'); diff --git a/lib/pbe.js b/lib/pbe.js index cf8456ba6..1f66bc94b 100644 --- a/lib/pbe.js +++ b/lib/pbe.js @@ -270,7 +270,7 @@ pki.encryptPrivateKeyInfo = function(obj, password, options) { var md = prfAlgorithmToMessageDigest(prfAlgorithm); // encrypt private key using pbe SHA-1 and AES/DES - var dk = forge.pkcs5.pbkdf2(password, salt, count, dkLen, md); + var dk = forge.pkcs5.pbkdf2((password === undefined)? "": password, salt, count, dkLen, md); var iv = forge.random.getBytesSync(ivLen); var cipher = cipherFn(dk); cipher.start(iv); @@ -345,6 +345,157 @@ pki.encryptPrivateKeyInfo = function(obj, password, options) { ]); return rval; }; +//----MOD BY SEBA----------------------------------------------------------------------- +/* +@param obj the ASN.1 ContentInfo object. + * @param password the password to encrypt with. + * @param options: + * algorithm the encryption algorithm to use + * ('aes128', 'aes192', 'aes256', '3des'), defaults to 'aes128'. + * count the iteration count to use. + * saltSize the salt size to use. + * prfAlgorithm the PRF message digest algorithm to use + * ('sha1', 'sha224', 'sha256', 'sha384', 'sha512') + * + * @return the ASN.1 EncryptedContentInfo. + * */ +pki.encryptContentInfo = function(obj, password, options) { + // set default options + options = options || {}; + options.saltSize = options.saltSize || 8; + options.count = options.count || 2048; + options.algorithm = options.algorithm || 'aes128'; + options.prfAlgorithm = options.prfAlgorithm || 'sha1'; + + // generate PBE params + var salt = forge.random.getBytesSync(options.saltSize); + var count = options.count; + var countBytes = asn1.integerToDer(count); + var dkLen; + var encryptionAlgorithm; + var encryptedData; + if(options.algorithm.indexOf('aes') === 0 || options.algorithm === 'des') { + // do PBES2 + var ivLen, encOid, cipherFn; + switch(options.algorithm) { + case 'aes128': + dkLen = 16; + ivLen = 16; + encOid = oids['aes128-CBC']; + cipherFn = forge.aes.createEncryptionCipher; + break; + case 'aes192': + dkLen = 24; + ivLen = 16; + encOid = oids['aes192-CBC']; + cipherFn = forge.aes.createEncryptionCipher; + break; + case 'aes256': + dkLen = 32; + ivLen = 16; + encOid = oids['aes256-CBC']; + cipherFn = forge.aes.createEncryptionCipher; + break; + case 'des': + dkLen = 8; + ivLen = 8; + encOid = oids['desCBC']; + cipherFn = forge.des.createEncryptionCipher; + break; + default: + var error = new Error('Cannot encrypt Content Info. Unknown encryption algorithm.'); + error.algorithm = options.algorithm; + throw error; + } + + // get PRF message digest + var prfAlgorithm = 'hmacWith' + options.prfAlgorithm.toUpperCase(); + var md = prfAlgorithmToMessageDigest(prfAlgorithm); + + // encrypt ContentInfo using pbe SHA-1 and AES/DES + var dk = forge.pkcs5.pbkdf2((password === undefined)? "": password, salt, count, dkLen, md); + var iv = forge.random.getBytesSync(ivLen); + var cipher = cipherFn(dk); + cipher.start(iv); + cipher.update(asn1.toDer(obj)); + cipher.finish(); + encryptedData = cipher.output.getBytes(); + + // get PBKDF2-params + var params = createPbkdf2Params(salt, countBytes, dkLen, prfAlgorithm); + + encryptionAlgorithm = asn1.create( + asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ + asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, + asn1.oidToDer(oids['pkcs5PBES2']).getBytes()), + asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ + // keyDerivationFunc + asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ + asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, + asn1.oidToDer(oids['pkcs5PBKDF2']).getBytes()), + // PBKDF2-params + params + ]), + // encryptionScheme + asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ + asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, + asn1.oidToDer(encOid).getBytes()), + // iv + asn1.create( + asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, iv) + ]) + ]) + ]); + + } else if(options.algorithm === '3des') { + // Do PKCS12 PBE + dkLen = 24; + + var saltBytes = new forge.util.ByteBuffer(salt); + var dk = pki.pbe.generatePkcs12Key(password, saltBytes, 1, count, dkLen); + var iv = pki.pbe.generatePkcs12Key(password, saltBytes, 2, count, dkLen); + var cipher = forge.des.createEncryptionCipher(dk); + cipher.start(iv); + cipher.update(asn1.toDer(obj)); + cipher.finish(); + encryptedData = cipher.output.getBytes(); + + encryptionAlgorithm = asn1.create( + asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ + asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, + asn1.oidToDer(oids['pbeWithSHAAnd3-KeyTripleDES-CBC']).getBytes()), + // pkcs-12PbeParams + asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ + // salt + asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, salt), + // iteration count + asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, + countBytes.getBytes()) + ]) + ]); + + } else { + var error = new Error('Cannot encrypt Content Info. Unknown encryption algorithm.'); + error.algorithm = options.algorithm; + throw error; + } + const rval = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ + // Version + asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, asn1.integerToDer(0).getBytes()), + //EncryptedContentInfo + asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ + // contentType + asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, asn1.oidToDer(pki.oids.data).getBytes()), + // contentEncryptionAlgorithm + encryptionAlgorithm, + // encryptedContent + asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, true, [ + asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, encryptedData) // Encrypted content + ]), + ]) + ]); + return rval; +}; /** * Decrypts a ASN.1 PrivateKeyInfo object. @@ -369,7 +520,7 @@ pki.decryptPrivateKeyInfo = function(obj, password) { // get cipher var oid = asn1.derToOid(capture.encryptionOid); - var cipher = pki.pbe.getCipher(oid, capture.encryptionParams, password); + var cipher = pki.pbe.getCipher(oid, capture.encryptionParams, (password === undefined)? "": password); // get encrypted data var encrypted = forge.util.createBuffer(capture.encryptedData); diff --git a/lib/pkcs12.js b/lib/pkcs12.js index cd06c494a..a4a7ed2d6 100644 --- a/lib/pkcs12.js +++ b/lib/pkcs12.js @@ -594,7 +594,7 @@ function _decryptSafeContents(data, password) { // get cipher oid = asn1.derToOid(capture.encAlgorithm); - var cipher = pki.pbe.getCipher(oid, capture.encParameter, password); + var cipher = pki.pbe.getCipher(oid, capture.encParameter, (password === undefined)? "": password); // get encrypted data var encryptedContentAsn1 = _decodePkcs7Data(capture.encryptedContentAsn1); @@ -790,7 +790,7 @@ function _decodeBagAttributes(attributes) { * friendlyName the friendly name to use. * generateLocalKeyId true to generate a random local key ID, * false not to, defaults to true. - * + * encryptCert true encrypt certSafeContents with password. //Please Note: Added for interoperability with (.NET Framework) -> System.Security.Cryptography.X509Certificates.X509Certificate2(cert, "password"); * @return the PKCS#12 PFX ASN.1 object. */ p12.toPkcs12Asn1 = function(key, cert, password, options) { @@ -799,6 +799,10 @@ p12.toPkcs12Asn1 = function(key, cert, password, options) { options.saltSize = options.saltSize || 8; options.count = options.count || 2048; options.algorithm = options.algorithm || options.encAlgorithm || 'aes128'; + options.encryptCert = options.encryptCert || false; + if(!('encryptCert' in options)) { + options.encryptCert = false; + } if(!('useMac' in options)) { options.useMac = true; } @@ -918,24 +922,43 @@ p12.toPkcs12Asn1 = function(key, cert, password, options) { var certSafeContents = asn1.create( asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, certSafeBags); - // ContentInfo - var certCI = - // PKCS#7 ContentInfo - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ - // contentType - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, - // OID for the content type is 'data' - asn1.oidToDer(pki.oids.data).getBytes()), - // content - asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, true, [ - asn1.create( - asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, - asn1.toDer(certSafeContents).getBytes()) - ]) - ]); + if(!options.encryptCert) { + // ContentInfo + var certCI = + // PKCS#7 ContentInfo + asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ + // contentType + asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, + // OID for the content type is 'data' + asn1.oidToDer(pki.oids.data).getBytes()), + // content + asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, true, [ + asn1.create( + asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, + asn1.toDer(certSafeContents).getBytes()) + ]) + ]); + }else if (password !== null) { + //Encrypted ContentInfo ContentInfo - MOD BY SEBA + var certCI = + // PKCS#7 ContentInfo + asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ + // contentType + asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, + // OID for the content type is 'encryptedData' + asn1.oidToDer(pki.oids.encryptedData).getBytes()), + // content + asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, true, [ + pki.encryptContentInfo(certSafeContents, password, options) + ]) + ]); + } else { + var error = new Error('Cannot encrypt Content Info. Needs a non empty password.'); + error.encryptCert = options.encryptCert; + throw error; + } contents.push(certCI); - } - + } // create safe contents for private key var keyBag = null; if(key !== null) { @@ -970,7 +993,6 @@ p12.toPkcs12Asn1 = function(key, cert, password, options) { bagAttrs ]); } - // SafeContents var keySafeContents = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [keyBag]); diff --git a/lib/x509.js b/lib/x509.js index 2877810c1..ccc74b4d9 100644 --- a/lib/x509.js +++ b/lib/x509.js @@ -2231,6 +2231,40 @@ function _fillMissingExtensionFields(e, options) { seq.push( asn1.create(asn1.Class.CONTEXT_SPECIFIC, 2, false, serialNumber)); } + } else if(e.name === 'authorityInfoAccess') { + e.value = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, []); + var accessDescription; + + for(var n = 0; n < e.accessDescriptions.length; ++n) { + accessDescription = e.accessDescriptions[n]; + var value = + asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, []); + var accessMethodOID; + + if(accessDescription.accessMethod === 'caIssuers') { + // handle caIssuers + accessMethodOID = oids['caIssuers']; + } else if(accessDescription.accessMethod === 'ocsp') { + // handle ocsp + accessMethodOID = oids['ocsp']; + } else { + throw new Error( + 'Invalid "authorityInfoAccess" accessMethod with value "' + + accessDescription.accessMethod + '"'); + } + + const oidDer = asn1.oidToDer(accessMethodOID); + value.value.push( + asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, oidDer)); + + const uri = accessDescription.accessLocation; + // Consider that the accessLocation is always a URI + value.value.push(asn1.create( + asn1.Class.CONTEXT_SPECIFIC, 6, false, uri + )); + + e.value.value.push(value); + } } else if(e.name === 'cRLDistributionPoints') { e.value = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, []); var seq = e.value.value; From 7323d5d097defd91f318db7083fd6fbf9bc7599f Mon Sep 17 00:00:00 2001 From: Sebastian-Dieguez Date: Tue, 4 Jun 2024 17:48:19 -0300 Subject: [PATCH 2/2] Clean Updated --- CHANGELOG.md | 27 --------- lib/oids.js | 4 -- lib/pbe.js | 155 +------------------------------------------------- lib/pkcs12.js | 62 +++++++------------- lib/x509.js | 34 ----------- 5 files changed, 22 insertions(+), 260 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7cca555a5..27d0e3a00 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,33 +1,6 @@ Forge ChangeLog =============== -## 1.3.2 - 2024-06-04 - -### Enhancement and interoperability -- **At [pkcs12.js] and [pbe.js].** - - Added (options.encryptCert) flag to allow encrypt [PKCS#7 ContentInfo], used in [PKCS#12 toPkcs12Asn1]. - - This ensures interoperability with [System.Security.Cryptography.X509Certificates.X509Certificate2(cert, password)]. - - Added suport for .NET interoperability for X509Certificate2(cert, password = "") - for do this set toPkcs12Asn1 with password = undefined. -### Completing OIDs -- **At [oids.js] and [x509.js].** - - Was added this: **'ocsp','caIssuers'** OIDs. - - Added setExtensions for this OIDs: 'ocsp','caIssuers'. - ```js - //Example of use: - { - name: 'authorityInfoAccess', //OCSP is Implemented in Fork https://github.com/SevanMelemedjian/forge.git - accessDescriptions: [ - { - accessMethod: 'ocsp', - accessLocation: 'http://yoursite.com/static/ocsp' - },{ - accessMethod: 'caIssuers', - accessLocation: 'http://yoursite.com/static/root.crt' - }] - } - ``` - ## 1.3.1 - 2022-03-29 ### Fixes diff --git a/lib/oids.js b/lib/oids.js index 9637beaf7..d1504eb16 100644 --- a/lib/oids.js +++ b/lib/oids.js @@ -177,7 +177,3 @@ _IN('1.3.6.1.5.5.7.3.2', 'clientAuth'); _IN('1.3.6.1.5.5.7.3.3', 'codeSigning'); _IN('1.3.6.1.5.5.7.3.4', 'emailProtection'); _IN('1.3.6.1.5.5.7.3.8', 'timeStamping'); - -// authorityInfoAccess methods OIDs -_IN('1.3.6.1.5.5.7.48.1', 'ocsp'); -_IN('1.3.6.1.5.5.7.48.2', 'caIssuers'); diff --git a/lib/pbe.js b/lib/pbe.js index 1f66bc94b..cf8456ba6 100644 --- a/lib/pbe.js +++ b/lib/pbe.js @@ -270,7 +270,7 @@ pki.encryptPrivateKeyInfo = function(obj, password, options) { var md = prfAlgorithmToMessageDigest(prfAlgorithm); // encrypt private key using pbe SHA-1 and AES/DES - var dk = forge.pkcs5.pbkdf2((password === undefined)? "": password, salt, count, dkLen, md); + var dk = forge.pkcs5.pbkdf2(password, salt, count, dkLen, md); var iv = forge.random.getBytesSync(ivLen); var cipher = cipherFn(dk); cipher.start(iv); @@ -345,157 +345,6 @@ pki.encryptPrivateKeyInfo = function(obj, password, options) { ]); return rval; }; -//----MOD BY SEBA----------------------------------------------------------------------- -/* -@param obj the ASN.1 ContentInfo object. - * @param password the password to encrypt with. - * @param options: - * algorithm the encryption algorithm to use - * ('aes128', 'aes192', 'aes256', '3des'), defaults to 'aes128'. - * count the iteration count to use. - * saltSize the salt size to use. - * prfAlgorithm the PRF message digest algorithm to use - * ('sha1', 'sha224', 'sha256', 'sha384', 'sha512') - * - * @return the ASN.1 EncryptedContentInfo. - * */ -pki.encryptContentInfo = function(obj, password, options) { - // set default options - options = options || {}; - options.saltSize = options.saltSize || 8; - options.count = options.count || 2048; - options.algorithm = options.algorithm || 'aes128'; - options.prfAlgorithm = options.prfAlgorithm || 'sha1'; - - // generate PBE params - var salt = forge.random.getBytesSync(options.saltSize); - var count = options.count; - var countBytes = asn1.integerToDer(count); - var dkLen; - var encryptionAlgorithm; - var encryptedData; - if(options.algorithm.indexOf('aes') === 0 || options.algorithm === 'des') { - // do PBES2 - var ivLen, encOid, cipherFn; - switch(options.algorithm) { - case 'aes128': - dkLen = 16; - ivLen = 16; - encOid = oids['aes128-CBC']; - cipherFn = forge.aes.createEncryptionCipher; - break; - case 'aes192': - dkLen = 24; - ivLen = 16; - encOid = oids['aes192-CBC']; - cipherFn = forge.aes.createEncryptionCipher; - break; - case 'aes256': - dkLen = 32; - ivLen = 16; - encOid = oids['aes256-CBC']; - cipherFn = forge.aes.createEncryptionCipher; - break; - case 'des': - dkLen = 8; - ivLen = 8; - encOid = oids['desCBC']; - cipherFn = forge.des.createEncryptionCipher; - break; - default: - var error = new Error('Cannot encrypt Content Info. Unknown encryption algorithm.'); - error.algorithm = options.algorithm; - throw error; - } - - // get PRF message digest - var prfAlgorithm = 'hmacWith' + options.prfAlgorithm.toUpperCase(); - var md = prfAlgorithmToMessageDigest(prfAlgorithm); - - // encrypt ContentInfo using pbe SHA-1 and AES/DES - var dk = forge.pkcs5.pbkdf2((password === undefined)? "": password, salt, count, dkLen, md); - var iv = forge.random.getBytesSync(ivLen); - var cipher = cipherFn(dk); - cipher.start(iv); - cipher.update(asn1.toDer(obj)); - cipher.finish(); - encryptedData = cipher.output.getBytes(); - - // get PBKDF2-params - var params = createPbkdf2Params(salt, countBytes, dkLen, prfAlgorithm); - - encryptionAlgorithm = asn1.create( - asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, - asn1.oidToDer(oids['pkcs5PBES2']).getBytes()), - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ - // keyDerivationFunc - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, - asn1.oidToDer(oids['pkcs5PBKDF2']).getBytes()), - // PBKDF2-params - params - ]), - // encryptionScheme - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, - asn1.oidToDer(encOid).getBytes()), - // iv - asn1.create( - asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, iv) - ]) - ]) - ]); - - } else if(options.algorithm === '3des') { - // Do PKCS12 PBE - dkLen = 24; - - var saltBytes = new forge.util.ByteBuffer(salt); - var dk = pki.pbe.generatePkcs12Key(password, saltBytes, 1, count, dkLen); - var iv = pki.pbe.generatePkcs12Key(password, saltBytes, 2, count, dkLen); - var cipher = forge.des.createEncryptionCipher(dk); - cipher.start(iv); - cipher.update(asn1.toDer(obj)); - cipher.finish(); - encryptedData = cipher.output.getBytes(); - - encryptionAlgorithm = asn1.create( - asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, - asn1.oidToDer(oids['pbeWithSHAAnd3-KeyTripleDES-CBC']).getBytes()), - // pkcs-12PbeParams - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ - // salt - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, salt), - // iteration count - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, - countBytes.getBytes()) - ]) - ]); - - } else { - var error = new Error('Cannot encrypt Content Info. Unknown encryption algorithm.'); - error.algorithm = options.algorithm; - throw error; - } - const rval = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ - // Version - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, asn1.integerToDer(0).getBytes()), - //EncryptedContentInfo - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ - // contentType - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, asn1.oidToDer(pki.oids.data).getBytes()), - // contentEncryptionAlgorithm - encryptionAlgorithm, - // encryptedContent - asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, true, [ - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, encryptedData) // Encrypted content - ]), - ]) - ]); - return rval; -}; /** * Decrypts a ASN.1 PrivateKeyInfo object. @@ -520,7 +369,7 @@ pki.decryptPrivateKeyInfo = function(obj, password) { // get cipher var oid = asn1.derToOid(capture.encryptionOid); - var cipher = pki.pbe.getCipher(oid, capture.encryptionParams, (password === undefined)? "": password); + var cipher = pki.pbe.getCipher(oid, capture.encryptionParams, password); // get encrypted data var encrypted = forge.util.createBuffer(capture.encryptedData); diff --git a/lib/pkcs12.js b/lib/pkcs12.js index a4a7ed2d6..cd06c494a 100644 --- a/lib/pkcs12.js +++ b/lib/pkcs12.js @@ -594,7 +594,7 @@ function _decryptSafeContents(data, password) { // get cipher oid = asn1.derToOid(capture.encAlgorithm); - var cipher = pki.pbe.getCipher(oid, capture.encParameter, (password === undefined)? "": password); + var cipher = pki.pbe.getCipher(oid, capture.encParameter, password); // get encrypted data var encryptedContentAsn1 = _decodePkcs7Data(capture.encryptedContentAsn1); @@ -790,7 +790,7 @@ function _decodeBagAttributes(attributes) { * friendlyName the friendly name to use. * generateLocalKeyId true to generate a random local key ID, * false not to, defaults to true. - * encryptCert true encrypt certSafeContents with password. //Please Note: Added for interoperability with (.NET Framework) -> System.Security.Cryptography.X509Certificates.X509Certificate2(cert, "password"); + * * @return the PKCS#12 PFX ASN.1 object. */ p12.toPkcs12Asn1 = function(key, cert, password, options) { @@ -799,10 +799,6 @@ p12.toPkcs12Asn1 = function(key, cert, password, options) { options.saltSize = options.saltSize || 8; options.count = options.count || 2048; options.algorithm = options.algorithm || options.encAlgorithm || 'aes128'; - options.encryptCert = options.encryptCert || false; - if(!('encryptCert' in options)) { - options.encryptCert = false; - } if(!('useMac' in options)) { options.useMac = true; } @@ -922,43 +918,24 @@ p12.toPkcs12Asn1 = function(key, cert, password, options) { var certSafeContents = asn1.create( asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, certSafeBags); - if(!options.encryptCert) { - // ContentInfo - var certCI = - // PKCS#7 ContentInfo - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ - // contentType - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, - // OID for the content type is 'data' - asn1.oidToDer(pki.oids.data).getBytes()), - // content - asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, true, [ - asn1.create( - asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, - asn1.toDer(certSafeContents).getBytes()) - ]) - ]); - }else if (password !== null) { - //Encrypted ContentInfo ContentInfo - MOD BY SEBA - var certCI = - // PKCS#7 ContentInfo - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ - // contentType - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, - // OID for the content type is 'encryptedData' - asn1.oidToDer(pki.oids.encryptedData).getBytes()), - // content - asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, true, [ - pki.encryptContentInfo(certSafeContents, password, options) - ]) - ]); - } else { - var error = new Error('Cannot encrypt Content Info. Needs a non empty password.'); - error.encryptCert = options.encryptCert; - throw error; - } + // ContentInfo + var certCI = + // PKCS#7 ContentInfo + asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ + // contentType + asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, + // OID for the content type is 'data' + asn1.oidToDer(pki.oids.data).getBytes()), + // content + asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, true, [ + asn1.create( + asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, + asn1.toDer(certSafeContents).getBytes()) + ]) + ]); contents.push(certCI); - } + } + // create safe contents for private key var keyBag = null; if(key !== null) { @@ -993,6 +970,7 @@ p12.toPkcs12Asn1 = function(key, cert, password, options) { bagAttrs ]); } + // SafeContents var keySafeContents = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [keyBag]); diff --git a/lib/x509.js b/lib/x509.js index ccc74b4d9..2877810c1 100644 --- a/lib/x509.js +++ b/lib/x509.js @@ -2231,40 +2231,6 @@ function _fillMissingExtensionFields(e, options) { seq.push( asn1.create(asn1.Class.CONTEXT_SPECIFIC, 2, false, serialNumber)); } - } else if(e.name === 'authorityInfoAccess') { - e.value = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, []); - var accessDescription; - - for(var n = 0; n < e.accessDescriptions.length; ++n) { - accessDescription = e.accessDescriptions[n]; - var value = - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, []); - var accessMethodOID; - - if(accessDescription.accessMethod === 'caIssuers') { - // handle caIssuers - accessMethodOID = oids['caIssuers']; - } else if(accessDescription.accessMethod === 'ocsp') { - // handle ocsp - accessMethodOID = oids['ocsp']; - } else { - throw new Error( - 'Invalid "authorityInfoAccess" accessMethod with value "' - + accessDescription.accessMethod + '"'); - } - - const oidDer = asn1.oidToDer(accessMethodOID); - value.value.push( - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, oidDer)); - - const uri = accessDescription.accessLocation; - // Consider that the accessLocation is always a URI - value.value.push(asn1.create( - asn1.Class.CONTEXT_SPECIFIC, 6, false, uri - )); - - e.value.value.push(value); - } } else if(e.name === 'cRLDistributionPoints') { e.value = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, []); var seq = e.value.value;