// // virtual methods // protected virtual AsymmetricKeyParameter GetPublicKey() { if (KeyInfo == null) { throw new System.Security.Cryptography.CryptographicException(SR.Cryptography_Xml_KeyInfoRequired); } if (_x509Enum != null) { AsymmetricKeyParameter key = GetNextCertificatePublicKey(); if (key != null) { return(key); } } if (_keyInfoEnum == null) { _keyInfoEnum = KeyInfo.GetEnumerator(); } // In our implementation, we move to the next KeyInfo clause which is an RSAKeyValue, DSAKeyValue or KeyInfoX509Data while (_keyInfoEnum.MoveNext()) { RSAKeyValue rsaKeyValue = _keyInfoEnum.Current as RSAKeyValue; if (rsaKeyValue != null) { return(rsaKeyValue.Key); } DSAKeyValue dsaKeyValue = _keyInfoEnum.Current as DSAKeyValue; if (dsaKeyValue != null) { return(dsaKeyValue.Key); } KeyInfoX509Data x509Data = _keyInfoEnum.Current as KeyInfoX509Data; if (x509Data != null) { _x509Collection = Utils.BuildBagOfCerts(x509Data, CertUsageType.Verification); if (_x509Collection.Count > 0) { _x509Enum = _x509Collection.GetEnumerator(); AsymmetricKeyParameter key = GetNextCertificatePublicKey(); if (key != null) { return(key); } } } } return(null); }
private IList <X509Certificate> BuildBagOfCerts() { var collection = new List <X509Certificate>(); if (KeyInfo != null) { foreach (KeyInfoClause clause in KeyInfo) { KeyInfoX509Data x509Data = clause as KeyInfoX509Data; if (x509Data != null) { collection.AddRange(Utils.BuildBagOfCerts(x509Data, CertUsageType.Verification)); } } } return(collection); }
// Try to decrypt the EncryptedKey given the key mapping public virtual byte[] DecryptEncryptedKey(EncryptedKey encryptedKey, RsaKeyParameters privateKey = null) { if (encryptedKey == null) { throw new ArgumentNullException(nameof(encryptedKey)); } if (encryptedKey.KeyInfo == null) { return(null); } IEnumerator keyInfoEnum = encryptedKey.KeyInfo.GetEnumerator(); KeyInfoName kiName; KeyInfoX509Data kiX509Data; KeyInfoRetrievalMethod kiRetrievalMethod; KeyInfoEncryptedKey kiEncKey; EncryptedKey ek = null; bool fOAEP = false; while (keyInfoEnum.MoveNext()) { kiName = keyInfoEnum.Current as KeyInfoName; if (kiName != null) { // Get the decryption key from the key mapping string keyName = kiName.Value; object kek = _keyNameMapping[keyName]; if (kek != null) { if (encryptedKey.CipherData == null || encryptedKey.CipherData.CipherValue == null) { throw new System.Security.Cryptography.CryptographicException(SR.Cryptography_Xml_MissingAlgorithm); } // kek is either a SymmetricAlgorithm or an RSA key, otherwise, we wouldn't be able to insert it in the hash table if (kek is KeyParameter kp) { return(EncryptedXml.DecryptKey(encryptedKey.CipherData.CipherValue, kp)); } else if (kek is ParametersWithIV piv) { return(EncryptedXml.DecryptKey(encryptedKey.CipherData.CipherValue, piv.Parameters as KeyParameter)); } // kek is an RSA key: get fOAEP from the algorithm, default to false fOAEP = (encryptedKey.EncryptionMethod != null && encryptedKey.EncryptionMethod.KeyAlgorithm == EncryptedXml.XmlEncRSAOAEPUrl); return(EncryptedXml.DecryptKey(encryptedKey.CipherData.CipherValue, (RsaKeyParameters)kek, fOAEP)); } break; } kiX509Data = keyInfoEnum.Current as KeyInfoX509Data; if (kiX509Data != null) { IList <X509Certificate> collection = Utils.BuildBagOfCerts(kiX509Data, CertUsageType.Decryption); foreach (X509Certificate certificate in collection) { if (privateKey != null) { if (encryptedKey.CipherData == null || encryptedKey.CipherData.CipherValue == null) { throw new System.Security.Cryptography.CryptographicException(SR.Cryptography_Xml_MissingAlgorithm); } fOAEP = (encryptedKey.EncryptionMethod != null && encryptedKey.EncryptionMethod.KeyAlgorithm == EncryptedXml.XmlEncRSAOAEPUrl); return(EncryptedXml.DecryptKey(encryptedKey.CipherData.CipherValue, privateKey, fOAEP)); } } break; } kiRetrievalMethod = keyInfoEnum.Current as KeyInfoRetrievalMethod; if (kiRetrievalMethod != null) { string idref = Utils.ExtractIdFromLocalUri(kiRetrievalMethod.Uri); ek = new EncryptedKey(); ek.LoadXml(GetIdElement(_document, idref)); try { //Following checks if XML dsig processing is in loop and within the limit defined by machine // admin or developer. Once the recursion depth crosses the defined limit it will throw exception. _xmlDsigSearchDepthCounter++; if (IsOverXmlDsigRecursionLimit()) { //Throw exception once recursion limit is hit. throw new CryptoSignedXmlRecursionException(); } else { return(DecryptEncryptedKey(ek, privateKey)); } } finally { _xmlDsigSearchDepthCounter--; } } kiEncKey = keyInfoEnum.Current as KeyInfoEncryptedKey; if (kiEncKey != null) { ek = kiEncKey.EncryptedKey; // recursively process EncryptedKey elements byte[] encryptionKey = DecryptEncryptedKey(ek, privateKey); if (encryptionKey != null) { // this is a symmetric algorithm for sure IBlockCipher blockSymAlg = CryptoHelpers.CreateFromName <IBlockCipher>(encryptedKey.EncryptionMethod.KeyAlgorithm); if (blockSymAlg == null) { IBufferedCipher bufferedSymAlg = CryptoHelpers.CreateFromName <IBufferedCipher>(encryptedKey.EncryptionMethod.KeyAlgorithm); if (bufferedSymAlg == null) { throw new System.Security.Cryptography.CryptographicException(SR.Cryptography_Xml_MissingAlgorithm); } } if (encryptedKey.CipherData == null || encryptedKey.CipherData.CipherValue == null) { throw new System.Security.Cryptography.CryptographicException(SR.Cryptography_Xml_MissingAlgorithm); } return(EncryptedXml.DecryptKey(encryptedKey.CipherData.CipherValue, new KeyParameter(encryptionKey))); } } } return(null); }