Подписание данных с помощью ключа RSA - PullRequest
0 голосов
/ 22 мая 2018

У меня есть команда openssl, которая прекрасно работает:

echo -n "my_password" | openssl pkeyutl -sign -inkey /home/ramunas/Downloads/id_rsa | base64 -w 0

и выводит требуемый результат:

Q9dyYKFvGOELAZYN8O18l30/bC/hVBm+7sy0DFJkspSvQa4bY7xGGsRina99ivxbdsu4BaakXDdA/X9wxP/Ll/GpEUS9xteiVNQkOEYOl27OAhe0OsC6zRDKpRPJEFhfLVt0cHlDILRZ0yuJLfv0UiwF0CTe4Xv5AN3RXrv28nIS8XA0o/TmCB5XlG12Zq7UdFoDF+j6oFXMyWAV9eXa1uQdNzIAm8wPn4e3lEz4v8p/M5PhLlAO2rBTEw79PiqFtKqlJ1OAZan8As02ejBjpe3t55dKuQke5+S1/7Zt7bZozDeswSMYbb643ZbLW+QN0AoO7pMy4w8qugzQZ/gnfw==

Ключ RSA (PKCS8):

MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCfHlwo+7jE6TKGGquuLDcrj+gPiWpl7QKpUAa8rqCs+A0iGbIM843U+uRx5mAhoBSJhBL9XPZss+IEKGy29K6bdy8sCXBvU+rjjPC/q91Sg5pw84063h8sOvV0UIFZVFZBt4Ax53qhOWFMAGtNB55LPvih71uz+iI5KneeS6OgAeBy1I+fJG1SiFDyOZsugma4f50ACXtI4hVtYSmM3/hY3XpWGQdUJPKByTfIxHg1v6EdMZ7mlOjYSFZxCVQRSXUAVf9ctPQQ4iA4gn69uveYH/fZQTc+7M3FGGsYVY2q31N+3jRbppOi6NqqISPckfXKnlTNkTkjXM0ZbZSvJrk3AgMBAAECggEAZjItpvTlmzLbjF4c3eTwGj53IWN0vroW93+6k/zknbNDXB98x+y1r5DkoHMCUxZpmlkFiUznyLFP/LOp/2fvrVJDLdlyKU6Qkk23YqOTpqd3zgvfLWv0QYgsleQO77zHGbYt09+EV4BvCU1LnVHDTTjIn9kH4PRKfsTTxwt1sBH//kXwZaRlvKxP0C9EGXPCymgdFO9RAhaVURDx3x7prKGRJbPDSMIP09elhChQ2fHvTDlqvrnr71hIR1ge8uGMkRta0gv3VyXpbAOrVJqxzmiccUIQoocWVLNCPXFZTe/7BFx1esLH4nGUwC57yiw9KudVhl5oeMIcHjKyrnoeIQKBgQDeuGqEqvGzlX/ZTt9S9LBj04OMA+0T2Lg/rg8pbn3MsqCLPikaf55Xpx5Le8fgc9cQzZYaLb22bEMAkl38EEttTK0ChWFnViGVYrxTDuQZA2eKljLrmuiynrjOdJq1Sro7bRsSOPYO32BwdGZ2/KJCJkocgRP2Mi9nALlrBfcRswKBgQC25QZIeynG2DHSR6rUTNhurVqbVHE5CWfmABdUHyg90y0DSjeKLad3z42Zln5mKfcapjWqL4443HAJ8ggdkyyYuif0RO4L2NBBKL/GxSjpeRgEZfmhOMgJLEy9dAzWSaiH1B5/MY1ZWxXWJBinOgu7ME6rrK5pEZDq/ySApkMQbQKBgBPx9fANkvmfIMToME2whf9amMQ4Mcn+NXnWb5spPvDO6lut5GZwGVEGMUtXOW4bUZ46mv+bKwskJNfvQ6VoHCkcnb3FDhT//J/xKKZThg/LY0Fg9AxvYfllB23NuXEU0RqzSaJXIYnxbSSE+Awd0bYU0bw9vvjkQ6R4xyITda3LAoGBALEcB4GZA1OzeEuRazQ7VjuXU+6nTx1UpnBsFis4INf979EHxdDhdRLows7AlZaJfOkpmz463xbhIP4AiytYog8j9hztwzdltgXjWBM8SeoNgdyAg8REIDIB3C56exPoMHOYThAOBDtLoVHFkrod085pcUV960eD4zot6UNLvhXhAoGBAITXSidOCGfkUVj8/oItR/IV+gwqFZFMoXDD8vJ/0G99Rjib4rWcX6B3NxamnNA6EfiGaMTdWZaxFbJOPh2K7OcOlDCWNpMvEQQyI0nhGKkKCujiTfBkSWkKDHdEAC/p0k2rAh4feYabdvX+ePmWAs6/X/syQ69jBk2Y6PhUsJH3

НоМне нужно подписать пароль с помощью C #, с помощью этот ответ я создал провайдера RSA.В основном это то же самое, что и в примере, но требуется добавить поиск байтов в одном месте, я подозреваю, что ключ имеет больше информации по сравнению с ключом в ссылке.Между прочим, я вывожу часть модуля в ключе с openssl и из c # они совпадают, за исключением первого шестнадцатеричного числа Modulus comparison

private RSACryptoServiceProvider CreateRsaProviderFromPrivateKey(string privateKey)
    {
        var privateKeyBits = System.Convert.FromBase64String(privateKey);

        var RSA = new RSACryptoServiceProvider();
        var RSAparams = new RSAParameters();

        using (BinaryReader binr = new BinaryReader(new MemoryStream(privateKeyBits)))
        {
            byte bt = 0;
            ushort twobytes = 0;
            twobytes = binr.ReadUInt16();
            if (twobytes == 0x8130)
                binr.ReadByte();
            else if (twobytes == 0x8230)
                binr.ReadInt16();
            else
                throw new Exception("Unexpected value read binr.ReadUInt16()");

            twobytes = binr.ReadUInt16();
            if (twobytes != 0x0102)
                throw new Exception("Unexpected version");

            bt = binr.ReadByte();
            if (bt != 0x00)
                throw new Exception("Unexpected value read binr.ReadByte()");

            for (int ii = 0; ii < 26; ii++) //!!! this one needs explanation
                binr.Read();

            RSAparams.Modulus = binr.ReadBytes(GetIntegerSize(binr));
            RSAparams.Exponent = binr.ReadBytes(GetIntegerSize(binr));
            RSAparams.D = binr.ReadBytes(GetIntegerSize(binr));
            RSAparams.P = binr.ReadBytes(GetIntegerSize(binr));
            RSAparams.Q = binr.ReadBytes(GetIntegerSize(binr));
            RSAparams.DP = binr.ReadBytes(GetIntegerSize(binr));
            RSAparams.DQ = binr.ReadBytes(GetIntegerSize(binr));
            RSAparams.InverseQ = binr.ReadBytes(GetIntegerSize(binr));
        }

        RSA.ImportParameters(RSAparams);
        return RSA;
    }

    private int GetIntegerSize(BinaryReader binr)
    {
        byte bt = 0;
        byte lowbyte = 0x00;
        byte highbyte = 0x00;
        int count = 0;
        bt = binr.ReadByte();
        if (bt != 0x02)
            return 0;
        bt = binr.ReadByte();

        if (bt == 0x81)
            count = binr.ReadByte();
        else
            if (bt == 0x82)
        {
            highbyte = binr.ReadByte();
            lowbyte = binr.ReadByte();
            byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
            count = BitConverter.ToInt32(modint, 0);
        }
        else
        {
            count = bt;
        }

        while (binr.ReadByte() == 0x00)
        {
            count -= 1;
        }
        binr.BaseStream.Seek(-1, SeekOrigin.Current);
        return count;
    }

С этим провайдером я пытаюсь «подписать» свои данные,но результат не совпадает с openssl

public void Test()
{
   RSACryptoServiceProvider provider = CreateRsaProviderFromPrivateKey(idRsa);
   string DataToEncrypt = "my_password";
   List<string> listStr = new List<string>();
   Encoding enco = Encoding.UTF8;
   listStr.Add(Convert.ToBase64String(provider.SignData(enco.GetBytes(DataToEncrypt), "SHA1")));
    listStr.Add(Convert.ToBase64String(provider.SignData(enco.GetBytes(DataToEncrypt), "SHA256")));
    listStr.Add(Convert.ToBase64String(provider.SignData(enco.GetBytes(DataToEncrypt), HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1)));
   listStr.Add(Convert.ToBase64String(provider.Encrypt(enco.GetBytes(DataToEncrypt), true)));
   listStr.Add(Convert.ToBase64String(provider.Encrypt(enco.GetBytes(DataToEncrypt), false)));
   listStr.Add(Convert.ToBase64String(provider.Encrypt(enco.GetBytes(DataToEncrypt), RSAEncryptionPadding.OaepSHA1)));
}

Ответы [ 2 ]

0 голосов
/ 14 июня 2018

Решил проблему, просто используя OpenSSL в Windows (скачал и собрал двоичные файлы с помощью этого учебника ).Единственное отличие состоит в том, что вы должны передать файл паролей и не можете прочитать выходные данные из командной строки (выходные данные командной строки не выводятся из файла Mach и не работают).Мой код ниже:

Encoding encoding = Encoding.Default;
string openSSLExe = "C:\\OpenSSL-Win32\\bin\\openssl.exe";


string unencodedPsw = "something";
string pkey = "MIIEvAIBADANB...";        //It comes from database, therefore needs to save each time.
string pwdFile = Path.GetTempFileName();
string rsaFile = Path.GetTempFileName();
string outFile = Path.GetTempFileName();

File.WriteAllBytes(pwdFile, encoding.GetBytes(unencodedPsw));
File.WriteAllBytes(rsaFile,  encoding.GetBytes(pkey));

string args = String.Format("pkeyutl -sign -in \"{0}\" -inkey \"{1}\" -out \"{2}\"", pwdFile, rsaFile, outFile);
var proc = new Process
{
    StartInfo = new ProcessStartInfo
    {
        FileName = openSSLExe,
        Arguments = args,
        UseShellExecute = false,
        RedirectStandardOutput = true,
        CreateNoWindow = true
    }
};

proc.Start();
proc.WaitForExit();

string encodedPsw = Convert.ToBase64String(File.ReadAllBytes(outFile));
File.Delete(pwdFile);
File.Delete(rsaFile);
File.Delete(outFile);

return encodedPsw;
0 голосов
/ 22 мая 2018

Проблема в том, что openssl pkeyutl -sign не делает то, что вы думаете, что делает.(Вы хотели openssl dgst -sign)

$ echo -n "my_password" | \
> openssl pkeyutl -sign -inkey rsa.key | \
> openssl rsautl -inkey rsa.key -verify -raw -hexdump
0000 - 00 01 ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
0010 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
0020 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
0030 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
0040 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
0050 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
0060 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
0070 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
0080 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
0090 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
00a0 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
00b0 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
00c0 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
00d0 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
00e0 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
00f0 - ff ff ff ff 00 6d 79 5f-70 61 73 73 77 6f 72 64   .....my_password

Обратите внимание, что оно содержит my_password в конце заполненного блока, а не дайджест этого значения.

openssl pkeyutl -sign принимает входные данныев качестве входных данных, отформатированных после дайджеста, в случае подписания PKCS # 1 это должен быть DER-кодированный DigestInfo, описывающий, какой алгоритм дайджеста использовался и каким был результирующий дайджест (https://tools.ietf.org/html/rfc2437#section-9.2.1 шаг 2).Это в значительной степени означает, что вы никогда не захотите использовать эту команду.

Сравните это с выводом openssl dgst -sign:

$ echo -n "my_password" | \
> openssl dgst -sha256 -sign rsa.key | \
> openssl rsautl -verify -raw -hexdump -inkey rsa.key
0000 - 00 01 ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
0010 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
0020 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
0030 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
0040 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
0050 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
0060 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
0070 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
0080 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
0090 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
00a0 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
00b0 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
00c0 - ff ff ff ff ff ff ff ff-ff ff ff ff 00 30 31 30   .............010
00d0 - 0d 06 09 60 86 48 01 65-03 04 02 01 05 00 04 20   ...`.H.e.......
00e0 - f6 e2 48 ea 99 4f 3e 34-2f 61 14 1b 8b 8e 3e de   ..H..O>4/a....>.
00f0 - 86 d4 de 53 25 7a bc 8d-06 ae 07 a1 da 73 fb 39   ...S%z.......s.9

И если вместо этого мы отправим вывод openssl dgst -sign в base64:

GP0L9sIrk0QV6r+ZfP42yq9pWGDF5OwdoStvolp+DKzSxpc+eSItpIJrt6VIkfOMeyJG3GZUSDf2
Z5iLTzZ+NAQBj0ay0Y0FH81rg2oTAtJ/vbh5+jB3Akgkct8xosJpjJDNaDIUb6gN+QcCS0g1Nbsn
YFetFoH7lX2oDmkaAWdiBquLmCdiA8lsRGs9YocuhDghj36TCjvrqS0ZheX0Oa1rM9xFMFATdFTg
BJffGWVoZzikZ6orVG0BZ2XOh6DvxBnjqZZQ40ru20bfq40qT1iZmf72bQ7/rayOcVNxDi09UV6+
kXYSz++mJvzpOe+MIwaFlrZVUlcgDXvKhZtbRQ==

Это должно быть то же значение, которое вы получаете при использовании подписей SHA256 с этим ключом в .NET.

...