none
CNG/BCrypt/NCrypt Importer une clef AES éphémère wrappée par une clef RSA persistante RRS feed

  • Discussion générale

  • Je suis en train d'écrire une mini archi client/serveur pour faire de la sécurité :

    • Le côté serveur génère des clefs AES wrappées avec une clef publique RSA
    • Le côté client (développé sur l'API CNG ncrypt.h+bcrypt.h) demande des clefs au serveur (quand il en a besoin)

    Voici ce que j'imagine :

    1. Côté client :
       - je créé une clef RSA persistante (avec NCryptCreatePersistedKey) une fois pour toute
       - j'exporte la partie publique de cette clef (avec NCryptExportKey + BCRYPT_RSAPUBLIC_BLOB)
       - j'envoie cette clef publique au serveur (selon un protocole encore à définir)
    2. Côté serveur :
       - je génère une clef AES aléatoire
       - je la wrappe avec la clef publique que j'ai réçue
       - je renvoie au client cette clef wrappée (selon un protocole encore à définir)
    3. De retour du côté client :   
       - je récupère la clef wrappée et je l'intègre dans un blob au format BCrypt.   
          -> comment construire un blob au format BCrypt ?
       - j'importe ce blob en tant que clef éphémère (avec BCryptImportKey)   
          -> comment importer une clef symétrique éphémère wrappée par une clef asymétrique persistante ?
       - maintenant je peux utiliser cette clef AES pour chiffrer des données...


    J'ai écrit un code qui devrait faire ce que je veux, mais il reste des problèmes non résolus...  
    Voici ce code : 

    void get_wrapped_aes_key ( PUCHAR rsa_pub_key_blob , ULONG rsa_pub_key_blob_size ,   
                         PUCHAR wrapped_aes_key_blob , PULONG wrapped_aes_key_blob_size )
        {
        // send the rsa public key (from buffer rsa_pub_key_blob) to the secu server
        // secu server generates a random AES key and wraps it with the rsa public key
        // receive the wrapped AES key and serialize it into a BCrypt blob
        // mem copy this blob into the buffer wrapped_aes_key_blob)
        }
    
    void create_persistent_key ( const wchar_t * key_name )
        {
        const wchar_t      * storage          = MS_PLATFORM_CRYPTO_PROVIDER ;
        NCRYPT_PROV_HANDLE   storage_provider = NULL ;
        NCRYPT_KEY_HANDLE    rsa_key          = NULL ;
    
        NCryptOpenStorageProvider( &storage_provider,storage,0 ) ;
        NCryptCreatePersistedKey( storage_provider,&rsa_key,BCRYPT_RSA_ALGORITHM,key_name,0,NCRYPT_OVERWRITE_KEY_FLAG ) ;
        NCryptFinalizeKey( rsa_key,0 ) ;
        NCryptFreeObject( rsa_key ) ;
        NCryptFreeObject( storage_provider ) ;
        }
    
    BCRYPT_KEY_HANDLE import_key_using_persistent_key ( const wchar_t * key_name )
        {
        const wchar_t      * storage          = MS_PLATFORM_CRYPTO_PROVIDER ;
        const wchar_t      * blob_type        = BCRYPT_RSAPUBLIC_BLOB ;
        BCRYPT_ALG_HANDLE    algo_provider    = NULL;
        NCRYPT_PROV_HANDLE   storage_provider = NULL;
        NCRYPT_KEY_HANDLE    rsa_key          = NULL;
        BCRYPT_KEY_HANDLE    bcrypt_rsa_key   = NULL;
        BCRYPT_KEY_HANDLE    imported_aes_key = NULL;
        BYTE                 rsa_pub_key_blob [500] ;
        DWORD                rsa_pub_key_blob_size = sizeof(rsa_pub_key_blob) ;
        BYTE                 wrapped_aes_key_blob [500] ;
        DWORD                wrapped_aes_key_blob_size = sizeof(wrapped_aes_key_blob) ;
    
        //------------------- retrieve the persistent key
        NCryptOpenStorageProvider( &storage_provider,storage,0 ) ;
        NCryptOpenKey( storage_provider,&rsa_key,key_name,0,0 ) ;
        NCryptExportKey( rsa_key,NULL,blob_type,NULL,rsa_pub_key_blob,rsa_pub_key_blob_size,&rsa_pub_key_blob_size,0 ) ;
    
        //------------------- get a symmetric key from the security server
        get_wrapped_aes_key( rsa_pub_key_blob,rsa_pub_key_blob_size,wrapped_aes_key_blob,&wrapped_aes_key_blob_size ) ;
    
        // mysterious conversion from  rsa_key  to   bcrypt_rsa_key 
    
        //------------------- import the security server
        BCryptOpenAlgorithmProvider( &algo_provider,BCRYPT_RSA_ALGORITHM,NULL,0 ) ;
        BCryptImportKey( algo_provider,bcrypt_rsa_key,BCRYPT_KEY_DATA_BLOB,&imported_aes_key,NULL,0,wrapped_aes_key_blob,wrapped_aes_key_blob_size,0 ) ;
        BCryptCloseAlgorithmProvider( algo_provider,0 ) ;
        NCryptFreeObject( storage_provider ) ;
        NCryptFreeObject( rsa_key ) ;
        return imported_aes_key ;
        }



    Le code du serveur n'étant pas encore écrit, la fonction get_wrapped_aes_key est vide, mais il reste la question :
    Comment construire un blob contenant une clef AES wrappée par une clef RSA ?

    Le fonction create_persistent_key fonctionne bien, j'ai quand même une question :
    Comment choisir la taille de la clef à générer ? 
    (j'obtiens des clefs 2048 bits, c'est ce que je veux, mais comment choisir autre chose ?)  

    Dans la fonction import_key_using_persistent_key : BCryptImportKey attend un BCRYPT_KEY_HANDLE comme clef de wrapping, mais ma clef persistante est un NCRYPT_KEY_HANDLE.  
    Et là, je ne vois pas du tout ce que je dois faire...

    Merci d'avance


    jeudi 1 avril 2021 14:46

Toutes les réponses

  • Bonjour,

    Selon la documentation pour Key Import and Export , dans la section Symmetric keys:
    "Typically, you first export a key by using the BCryptExportKey function before importing by using the BCryptImportKey function. The functions are designed to enable encryption of exported and imported keys by using the hExportKey and hImportKey parameters; however, the Microsoft implementation of these functions does not support encryption of exported and imported keys."

    Peut-être ils manquent les paramètres hExportKey et hImportKey.


    Coridialement,

    Nina


    Microsoft propose ce service gratuitement, dans le but d'aider les utilisateurs et d'élargir les connaissances générales liées aux produits et technologies Microsoft. Ce contenu est fourni "tel quel" et il n'implique aucune responsabilité de la part de Microsoft.

    vendredi 2 avril 2021 09:25
    Modérateur