2017-07-31 8 views
0

Je suis en train de porter une fonction de signature RSA écrit en C#, de la (relativement facile à utiliser) méthode RSACryptoServiceProvider.SignHash, au CNG API, afin d'utiliser un cryptographic service provider spécifique..NET - Porting RSACryptoServiceProvider au CNG pour les données de signature

Ceci est la fonction d'origine (avant le portage):

private static byte[] SignDigest(RSAParameters keyMaterial, byte[] digest, string hashAlgo) 
    { 
     using (var cryptoProvider = new RSACryptoServiceProvider()) 
     { 
      cryptoProvider.ImportParameters(keyMaterial); 
      // hashAlgo can only be one of "SHA1", "SHA256", "SHA384" and "SHA512". 
      return cryptoProvider.SignHash(digest, CryptoConfig.MapNameToOID(hashAlgo)); 
     } 
    } 

assez simple, vous ne pensez pas? Lors du portage au CNG, c'est le meilleur que je pouvais faire jusqu'à présent:

private static byte[] SignDigest(RSAParameters keyMaterial, byte[] digest, string hashAlgo) 
    { 
     var size = 6 * 4 + keyMaterial.Exponent.Length + keyMaterial.Modulus.Length + keyMaterial.P.Length + keyMaterial.Q.Length; 
     var keyBlob = new byte[size];    
     using (var writer = new BinaryWriter(new MemoryStream(keyBlob))) 
     { 
      // This is BCRYPT_RSAKEY_BLOB structure (https://msdn.microsoft.com/en-us/library/windows/desktop/aa375531(v=vs.85).aspx). 
      writer.Write(0x32415352); // BCRYPT_RSAPRIVATE_MAGIC 
      writer.Write(keyMaterial.Modulus.Length * 8); // BitLength 
      writer.Write(keyMaterial.Exponent.Length); // cbPublicExp 
      writer.Write(keyMaterial.Modulus.Length); // cbModulus 
      writer.Write(keyMaterial.P.Length); // cbPrime1 
      writer.Write(keyMaterial.Q.Length); // cbPrime2 
      writer.Write(keyMaterial.Exponent); // PublicExponent 
      writer.Write(keyMaterial.Modulus); // Modulus 
      writer.Write(keyMaterial.P); // Prime1 
      writer.Write(keyMaterial.Q); // Prime2 
     } 

     // Function NCryptImportKey uses "RSAPRIVATEBLOB" to indicate a BCRYPT_RSAPRIVATE_BLOB structure. 
     // See https://msdn.microsoft.com/en-us/library/windows/desktop/aa376276(v=vs.85).aspx. 

     var key = CngKey.Import(keyBlob, new CngKeyBlobFormat("RSAPRIVATEBLOB"), _myProvider); 

     IntPtr pPaddingInfo = question; // What do I specify here? 
     byte[] pbHashValue = question; // Should I calculate hash from digest? How can I make sure it will be valid for verification? 
     byte[] pbSignature = question; // Is the signature size related to hash size? Or RSA key size? 
     int dwFlags = question; // Should I use BCRYPT_PAD_PKCS1 here or simply zero? 

     int pcbResult; 
     int result; 

     using (var hKey = key.Handle) 
     { 
      result = NCryptSignHash(hKey, pPaddingInfo, pbHashValue, pbHashValue.Length, pbSignature, pbSignature.Length, out pcbResult, dwFlags); 
     } 

     if (result != 0) 
      throw new Exception(); 

     return TrimArray(pbSignature, pcbResult); 
    } 

    // As described on https://msdn.microsoft.com/en-us/library/windows/desktop/aa376295(v=vs.85).aspx. 
    [DllImport("ncrypt.dll")] 
    internal static extern NCryptErrorCode NCryptSignHash(
     SafeNCryptKeyHandle hKey, 
     IntPtr pPaddingInfo, 
     [MarshalAs(UnmanagedType.LPArray)] byte[] pbHashValue, 
     int cbHashValue, 
     [MarshalAs(UnmanagedType.LPArray)] byte[] pbSignature, 
     int cbSignature, 
     out int pcbResult, 
     int dwFlags); 

je peux importer avec succès la clé CNG, mais je ne sais pas comment effectuer l'opération de signature. Toute aide est la bienvenue ...

Répondre

1

Si vous êtes sur 4.6 .NET ou plus, puis après var key = CngKey.Import(...)

using (RSACng rsa = new RSACng(key)) 
{ 
    // Consider changing your signature to take a HashAlgorithmName instead of string. 
    // I'm assuming you want RSA-SSA PKCS#1 v1.5 instead of RSA-SSA-PSS. 
    return rsa.SignHash(digest, new HashAlgorithmName(hashAlgo), RSASignaturePadding.Pkcs1); 
} 

Ou vous pouvez simplement vérifier https://referencesource.microsoft.com/#System.Core/System/Security/Cryptography/RsaCng.cs,672daeef0962f4ad si vous voulez voir les P/Invoque (en supposant que vous ne faites rien qui viole la licence de referencesource.microsoft.com).