Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Clean Updated
  • Loading branch information
Sebastian-Dieguez committed Jun 4, 2024
commit 7323d5d097defd91f318db7083fd6fbf9bc7599f
27 changes: 0 additions & 27 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
4 changes: 0 additions & 4 deletions lib/oids.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
155 changes: 2 additions & 153 deletions lib/pbe.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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.
Expand All @@ -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);
Expand Down
62 changes: 20 additions & 42 deletions lib/pkcs12.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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) {
Expand All @@ -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;
}
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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]);
Expand Down
34 changes: 0 additions & 34 deletions lib/x509.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down