Есть ли способ аутентификации YubiKey из автономного приложения C # без подключения к интернету? - PullRequest
0 голосов
/ 17 апреля 2019

Мне нужен какой-то способ аутентификации пользователя или пары ключей от YubiKey на компьютере с воздушным зазором (без подключения к Интернету). Желательно из приложения C # / .NET.

По сути, мне нужно убедиться, что вставленный YubiKey дает пользователю надлежащее разрешение на использование моего приложения.

Моей первой идеей было создать пару ключей RSA, сохранить закрытый ключ на YubiKey и открытый ключ в моем приложении. Затем я бы проверил пару ключей с помощью gpg. Однако этот подход не работает:

C: \ Program Files (x86) \ GnuPG \ bin> gpg --card-status

gpg: не удалось выбрать openpgp: такого устройства нет

gpg: карта OpenPGP недоступна: такого устройства нет

Затем я использовал YubiKey manager, чтобы сгенерировать пару ключей и сертификат и сохранить их на устройстве. Я могу увидеть сертификат с помощью команды Windows CertUtil , но не знаю, какие аргументы передать CertUtil -verifykeys [KeyContainerName CACertFile] , поскольку я не знаю имени контейнера.

Ответы [ 2 ]

1 голос
/ 18 апреля 2019

После некоторых поисков я нашел это решение на основе (https://www.codeproject.com/Articles/240655/Using-a-Smart-Card-Certificate-with-NET-Security-i)

Шаг 1: используйте ykman для установки пары секретный / открытый ключ

ykman piv generate-key -a RSA2048 -F PEM --touch-policy НИКОГДА 9e "c: \ dev \ License \ ykeys \ my_key.pub"

Эта команда создает пару открытых / закрытых ключей RSA. Закрытый ключ сохраняется вустройство в слоте 9e и при сохранении открытого ключа в файле "my_key.pub"

Шаг 2: используйте ykman для создания самозаверяющего сертификата

ykman piv generate-Certificate -s "my_key_test" -d 365 9e "c: \ dev \ License \ ykeys \ my_key.pub"

Эта команда создает самозаверяющий сертификат X.509 и сохраняет его на одном устройстве.

Шаг 3: экспортный сертификат

ykman piv экспортный сертификат -F PEM 9e "c: \ dev \ License \ ykeys \ my_key_crt.pem"

ThisКоманда создает копию сертификата из шага 2 в my_key_crt.pem

Шаг 4: используйте программу C # для проверки пары открытого / секретного ключей

using System;
using System.IO;
using System.Linq;
using System.Security;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;

namespace TestCSPSmartCard
{
class Program
{
    static unsafe void Main(string[] args)
    {
        //PKI provider name comes from system registry or the output  
        //of "certutil -scinfo" command
        //The container name comes from the output of "certutil -scinfo" command
        const string 
            pkiProvider = "Microsoft Base Smart Card Crypto Provider", 
            container = "b51a653f-f451-c1d4-0841-5ace955fc101";

        try
        {
            //'123456' is the default 
            SecureString smartCardPin;
            char[] scPwd = { '1', '2', '3', '4', '5', '6' };
            fixed(char* pChars = scPwd)       
            {   
                smartCardPin = new SecureString(pChars, scPwd.Length);       
            }

            //Construct CspParameters object. 
            //Omitting last two arguments will cause Windows to display a dialog
            //prompting user for the SmartCard PIN.
            CspParameters csp = 
                new CspParameters(1,
                    pkiProvider,
                    container,
                    new System.Security.AccessControl.CryptoKeySecurity(),
                    smartCardPin);

            byte[] toSign = new byte[20];
            Random rnd = new Random((int)DateTime.Now.Ticks);
            rnd.NextBytes(toSign);

            Console.WriteLine("Data to sign : " + BitConverter.ToString(toSign));

            RSACryptoServiceProvider rsaCsp = new RSACryptoServiceProvider(csp);
            RSAPKCS1SignatureFormatter rsaSign = new RSAPKCS1SignatureFormatter(rsaCsp);
            rsaSign.SetHashAlgorithm("SHA1");
            byte[] signature = rsaSign.CreateSignature(toSign);

            Console.WriteLine();
            Console.WriteLine("Signature: " + BitConverter.ToString(signature));

            RSACryptoServiceProvider rsaCsp2 = FromPublicKey(args.FirstOrDefault());

            RSAPKCS1SignatureDeformatter rsaVerify = new RSAPKCS1SignatureDeformatter(rsaCsp2);
            rsaVerify.SetHashAlgorithm("SHA1");
            bool verified = rsaVerify.VerifySignature(toSign, signature);

            Console.WriteLine();
            Console.WriteLine("Signature verified [{0}]", verified);
        }
        catch (Exception ex)
        {
            Console.WriteLine("Crypto error: " + ex.Message);
        }

        Console.WriteLine("done!");
    }

    private static RSACryptoServiceProvider FromPublicKey(string keyFile = null)
    {
        //Generated from PEM public key file using https://superdry.apphb.com/tools/online-rsa-key-converter
        const string xmlPubKey =
            @"<RSAKeyValue><Modulus>2mdYz5yV59K0PMO6HCxBA7gVWtbmNY+dwYOc14H5DTD7zQ64CHpxAQOAexFx5uQKaxIR8UjZOikOwO+NWMvQ4/DCIHu3WwK2/M07JQ3LYeeJ8L28RSfb9S7CCMvJ7sDOmVMB4otfQwqYvMri9QWYVe/9jWIyp3LezAUyFTGnA2OeMiVaZa2gsI5+v4HkuY3ZD9KIdUgp3Wt0SFTe1jRKAaqJhp8f3Lh0CRaYoukeq0XAhhh9k55o7wLCp0XZgSZzOPeuNL+at20Tx9BRcb/9odlmFoHn/0P0X57a1yKhKRGUIri3gfu2BJ2BnXOUy+iSk1VNWRixuMsxee059Gg7Uw==</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";

        if (keyFile != null)
        {
            FileInfo cerFile = new FileInfo(keyFile);

            if (cerFile.Exists)
            {
                X509Certificate2 cert = new X509Certificate2();

                Console.WriteLine($"Importing public key from {cerFile.FullName}");

                cert.Import(cerFile.FullName);

                return (RSACryptoServiceProvider)cert.PublicKey.Key;
            }
        }
        RSACryptoServiceProvider result = new RSACryptoServiceProvider();
        result.FromXmlString(xmlPubKey);

        return result;
    }
}
}
0 голосов
/ 17 апреля 2019

U2F и Webauthn можно использовать для полной аутентификации токена.Yubico использует Java на GitHub , и хотя двоичная загрузка отсутствует, вы можете легко скомпилировать ее, следуя описанию на странице.Сервер поставляется с демонстрационным сервером , который позволяет вам выполнять первые тесты, особенно когда речь идет о тестировании реализации на стороне клиента.Для этого также есть библиотеки, предоставляемые Yubico, которые вы также можете найти на Yubico .Приятной особенностью U2F и Webauthn является то, что оба они поддерживаются многими современными браузерами из коробки, поэтому, выполнив некоторое волшебство Javascript (по существу, navigator.credentials.get(...) для запуска процесса аутентификации токена), вы можете заставить все работать.Демо-сервер поставляется с HTML-страницей, которая содержит все необходимое для U2F или Webauthn.

...