2016-12-28 2 views
0

Les fonctions CryptVerifyMessageSignature et CryptDecryptMessage me permettent de vérifier si une signature S/MIME est valide (ou de déchiffrer des données cryptées dans CryptDecryptMessage) et également de renvoyer le certificat utilisé pour la signature (ou le cryptage). Cependant, il n'y a pas d'informations sur les algorithmes réellement utilisés pour la signature et le chiffrement. Comment puis-je obtenir cette information? J'utilise C# mais tout échantillon ou indice C/C++ est également le bienvenu.Comment déterminer l'algorithme de hachage et de chiffrement du message S/MIME avec Win32 CryptoAPI?

Edit: extrait de code de vérification de signature (tout le code est très grand pour l'inclure ici) ajouté sur demande

IntPtr pbDetachedSignBlob = IntPtr.Zero; 
uint cbDetachedSignBlob = (uint)signatureBytes.Length; 
IntPtr pbContent = IntPtr.Zero; 
uint cbContent = (uint)data.Length; 

pbDetachedSignBlob = Marshal.AllocHGlobal((int)cbDetachedSignBlob); 
Marshal.Copy(signatureBytes, 0, pbDetachedSignBlob, (int)cbDetachedSignBlob); 
pbContent = Marshal.AllocHGlobal((int)cbContent); 
Marshal.Copy(data, 0, pbContent, (int)cbContent); 
IntPtr[] messageArray = { pbContent }; 
uint[] messageSizeArray = { cbContent }; 

GCHandle messageArrayHandle = GCHandle.Alloc(messageArray, GCHandleType.Pinned); 
IntPtr messageArrayPtr = (IntPtr)messageArrayHandle.AddrOfPinnedObject(); 

int ret = CryptoApiFuncs.MessageFuncs.CryptVerifyDetachedMessageSignature(pVerifyPara, 0, pbDetachedSignBlob, cbDetachedSignBlob, 1, messageArrayPtr, ref messageSizeArray[0], ref pSignerCert); 
+0

peut vous partager le code que vous utilisez pour? –

+1

@CiroCorvino J'ai ajouté le code bien que je ne sois pas sûr de savoir comment cela aide. Je n'ai aucun problème avec ce code, ça fonctionne très bien. Ça fait juste une chose différente. – Alex

Répondre

0

Le api que vous utilisez, effectuer des contrôles de validité de la signature numérique qui va de pair avec des documents et ainsi de suite .. cette vérification est faite contre un certificat, dont les informations sont contenues dans la structure CERT_CONTEXT (pSignerCert) dans laquelle à son tour il est contenu une structure CERT_INFO (champ de structure pCertInfo CERT_CONTEXT).

vous pouvez trouver CERT_CONTEXT Dans infos sur le type standard de codage utilisé certicat (X509_ASN_ENCODING ou PKCS_7_ASN_ENCODING).

Dans CERT_INFO vous pouvez trouver CRYPT_ALGORITHM_IDENTIFIER et d'autres infos plus détaillées.

Pour une documentation sur CryptVerifyDetachedMessageSignature apis et structures connexes:

EDIT:

système de signature numérique fonctionne généralement la création d'un hachage des données à signer (SHA1 niveau minimum standard certificats anciens, maintenant les nouveaux certificative partent d'un niveau de SHA256 ..), alors ce hachage se crypté avec un privé clé utilisant un algorithme de cryptographie asymétrique (RSA). Lorsque le message est reçu, il est décrypté avec la clé publique contenue dans le certificat publié publiquement, puis la date est hachée avec le bon algorithme, déclaré dans le certificat (du point de vue du programme, voir la structure champs sur) et si les deux hachages (un dans le même certificat qui va avec les données, et l'autre calculé sur le client qui vérifie la signature numérique) correspondent, alors il est vérifié que les données ne sont pas corrompues ou modifiées autre que l'auteur, et si le certificat est délivré par une autorité de certification valide, l'auteur est également identifié de manière sûre.

+0

Ceci est l'information que j'ai déjà. Comme je l'ai écrit dans le post, je n'ai aucun problème à obtenir les certificats utilisés pour la signature et le cryptage. Je ne peux pas trouver l'algorithme utilisé pour cela. CRYPT_ALGORITHM_IDENTIFIER vous avez mentionné correspond à l'algorithme utilisé pour signer le certificat lui-même, pas les données signées avec la clé de ce certificat. Par exemple, j'ai un message qui est signé avec SHA1 alg tandis que le certificat lui-même est signé avec SHA256 alg. – Alex

+0

les informations (clé publique et algorithme) sur la signature de données avec la clé privée que vous pouvez trouver dans le champ CERT_INFO: CERT_PUBLIC_KEY_INFO SubjectPublicKeyInfo, qui à son tour signale les infos de l'algorithme toujours dans une structure CRYPT_ALGORITHM_IDENTIFIER. J'ai mentionné cela à propos des autres informations plus détaillées ... –

+0

Encore une fois, tout ce que vous avez mentionné concerne le certificat. Je n'ai pas besoin de cette information, j'ai déjà tout extrait de CERT_CONTEXT, CERT_INFO et CERT_PUBLIC_KEY_INFO. Je suis conscient de ces structures et j'ai déjà toutes les informations d'eux. Maintenant, j'ai besoin de l'info de l'algorithme qui a été utilisé pour signer le message. Il n'est pas contenu dans le certificat (par exemple, je peux utiliser le même certificat pour signer avec différents algorithmes). – Alex

1

Impossible de trouver le moyen de le faire directement via CryptoAPI mais a réussi à accomplir cette classe avec System.Security.Cryptography.Pkcs.SignedCms:

SignedCms cms = new SignedCms(new ContentInfo(data)); 
cms.Decode(signature); 
string algName = cms.SignerInfos[0].DigestAlgorithm.FriendlyName; 

où les données sont le message d'octets en cours de vérification et signature est la signature octets détachés.

Le code de production doit également être prêt à attendre des valeurs non uniques dans la collection SignerInfos, mais l'exemple de code affiche l'idée.

De la même façon, la classe EnvelopedCms fournit les détails sur l'algorithme de chiffrement du message:

EnvelopedCms cms = new EnvelopedCms(); 
cms.Decode(data); 
string s = cms.ContentEncryptionAlgorithm.Oid.FriendlyName;