Проблемы с созданием подписи ECDSA в .Net - PullRequest
0 голосов
/ 04 сентября 2018

У меня проблемы с созданием подписи в OpenSSL.Net, которая проверяется в командной строке OpenSSL.

Моя спецификация такая:

$ openssl ecparam -name prime192v1 -genkey -noout -out priv192v1B.pem
$ openssl ec -in priv192v1B.pem -pubout -out pub192v1B.pem
read EC key
writing EC key
$ openssl dgst -sha256 -sign priv192v1B.pem -out cmdlineSig192v1B.bin <        ./testCardDataB.bin
$ openssl dgst -sha256 -verify pub192v1B.pem -signature cmdlineSig192v1B.bin < ./testCardDataB.bin
Verified OK

, где testCardDataB.bin создается с помощью приведенного ниже кода C #, который также создает testCardSigB.bin. Я должен написать код на C #, чтобы сделать подпись, которая проверяется нормально с помощью командной строки OpenSSL. Если мой код правильный, то эта командная строка также должна работать:

$ openssl dgst -sha256 -verify pub192v1B.pem -signature testCardSigB.bin < ./testCardDataB.bin
Verification Failure

Но это не так, поэтому мой C # делает что-то не так. Вот C #:

        private void OsslTestSignature()
    {
        PrintToFeedback("Duplicating ecdsa_example.sh IN OPENSSL...");
        //openssl ecparam -name prime192v1 -genkey -noout -out priv192v1B.pem
        string privPemB64 = "MF8CAQEEGMrXsw/qyViETP1eMx/AWCOB0iPdrknfb6AKBggqhkjOPQMBAaE0AzIABJLZCUtkaxiPsguGULH5NxVSpdSraU08X+yPizrXODuiXtK3JguVnfO8Ii2pFEN8iQ=="; // priv192v1B.pem
        byte[] keyData = Convert.FromBase64String(privPemB64);
        string szkeyData = ByteArrayToHexString(keyData);
        //openssl dgst -sha256 -sign priv192v1B.pem -out cmdlineSig192v1B.bin < ./testCardDataB.bin
        string sigKey = GetIndexedElementFromAsn1ObjectAsString(szkeyData, 1, true);  // D is the Private Key
        OpenSSL.Core.BigNumber dNumber = OpenSSL.Core.BigNumber.FromHexString(sigKey);
        string szmsg = "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223";
        byte[] message = HexStringToByteArray(szmsg);
        System.Security.Cryptography.SHA256 mySHA256 = System.Security.Cryptography.SHA256Managed.Create();
        byte[] hash = mySHA256.ComputeHash(message);
        OpenSSL.Crypto.MessageDigestContext md_ctx = new OpenSSL.Crypto.MessageDigestContext(OpenSSL.Crypto.MessageDigest.ECDSA);
        //byte[] digest = md_ctx.Digest(message); // try this in case the hash happens automagically - NO
        byte[] digest = md_ctx.Digest(hash);
        OpenSSL.Core.Asn1Object curveObject = new OpenSSL.Core.Asn1Object("prime192v1");
        OpenSSL.Crypto.EC.Key key = OpenSSL.Crypto.EC.Key.FromCurveName(curveObject);
        var rc = key.GL_SetPrivateKey(dNumber);
        key.GenerateKey(); // ec_key_simple_generate_key uses existing private key
        var check = key.CheckKey(); // true
        /* create signature */
        byte[] sigBytes = new byte[key.Size];
        var sigSize = key.Sign(
            0,                 // type???
            digest,            // md_ctx.Digest(hash)
            /*out*/ sigBytes); // sigBytes gets filled with the signature
        if (null == sigBytes)
        {
            PrintToFeedback("Signature generation failed");
        }
        else
        {
            Array.Resize(ref sigBytes, (int)sigSize); // needed for self verify!
            PrintToFeedback("msg: " + szmsg);
            PrintToFeedback("sig: " + ByteArrayToHexString(sigBytes));
            File.WriteAllBytes("testCardDataB.bin", HexStringToByteArray(szmsg));
            File.WriteAllBytes("testCardSigB.bin", sigBytes);
            bool selfVerify = key.Verify(0, digest, sigBytes);
            PrintToFeedback("Self Verify: " + selfVerify.ToString());
        }
    }

где GL_SetPrivateKey () - это то, что я добавил в ManagedOpenSSL: key.cs:

public int GL_SetPrivateKey(BigNumber pNewKey)
{
  return Native.EC_KEY_set_private_key(ptr, pNewKey.Handle);
}

GetIndexedElementFromAsn1ObjectAsString анализирует правильно:

0 1
1 #cad7b30feac958844cfd5e331fc0582381d223ddae49df6f
2 [0]1.2.840.10045.3.1.1
3 [1]#0332000492D9094B646B188FB20B8650B1F9371552A5D4AB694D3C5FEC8F8B3AD7383BA25ED2B7260B959DF3BC222DA914437C89

по сравнению с командной строкой:

$ openssl asn1parse -inform PEM -dump  < ./priv192v1B.pem
0:d=0  hl=2 l=  95 cons: SEQUENCE
2:d=1  hl=2 l=   1 prim: INTEGER           :01
5:d=1  hl=2 l=  24 prim: OCTET STRING
  0000 - ca d7 b3 0f ea c9 58 84-4c fd 5e 33 1f c0 58 23   ......X.L.^3..X#
  0010 - 81 d2 23 dd ae 49 df 6f-                          ..#..I.o
31:d=1  hl=2 l=  10 cons: cont [ 0 ]
33:d=2  hl=2 l=   8 prim: OBJECT            :prime192v1
43:d=1  hl=2 l=  52 cons: cont [ 1 ]
45:d=2  hl=2 l=  50 prim: BIT STRING
  0000 - 00 04 92 d9 09 4b 64 6b-18 8f b2 0b 86 50 b1 f9   .....Kdk.....P..
  0010 - 37 15 52 a5 d4 ab 69 4d-3c 5f ec 8f 8b 3a d7 38   7.R...iM<_...:.8
  0020 - 3b a2 5e d2 b7 26 0b 95-9d f3 bc 22 2d a9 14 43   ;.^..&....."-..C
  0030 - 7c 89                                             |.

Это вывод PrintToFeedback:

Duplicating ecdsa_example.sh IN OPENSSL...
msg: 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223
sig: 3036021900B443A7B77E71FF1054F417AD76FC2120159B0E070B7E008B021900DDE7DC267152BACD049229B32C002560F20DE512E5B0209F
Self Verify: True

Большая картинка:

  • извлечение D из priv ~ .pem
  • установить кривую ECDSA и получить ключ
  • установить закрытый ключ ключа на D от priv ~ .pem
  • сделать подпись
  • изменить размер массива - самопроверка завершится неудачей без этого шага
  • проверить подпись
  • сохранить данные для проверки в командной строке

Вот выходные файлы:

-rwxrwx---+ 1 Larry Larry 35 Sep  4 09:29 testCardData.bin
000000 04 01 02 03 04 05 80 01 49 54 50 31 01 00 01 00
000010 00 02 fa f0 fe 01 01 00 00 00 00 00 00 00 00 00
000020 00 00 01
000023
-rwxrwx---+ 1 Larry Larry 54 Sep  4 09:29 testCardSig.bin
000000 30 34 02 18 37 f5 75 fd dc 0f 80 8a 46 6d 24 46
000010 70 13 1e 50 42 82 c0 67 65 37 09 49 02 18 5e b6
000020 6f 0f d7 ea 14 d0 b9 6a 1e 88 56 a2 e5 6c 8b f0
000030 8d 7f 47 74 1f 8e

Подпись из .Net в двоичном формате PEM, как и в командной строке:

$ od -t x1 -A x cmdlineSig192v1B.bin
000000 30 35 02 18 6c dc af 35 9f 22 7e df 8e 49 77 91
000010 ab 07 a6 1d 7f d2 53 ee af a9 1e 44 02 19 00 d7
000020 e4 ef 25 e7 d9 02 cb fb be 23 86 23 d2 90 f2 2f
000030 dd 68 b3 10 dc c9 53

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

  • Как вы должны установить закрытый ключ в OpenSSL.Net?
  • Что такое параметр типа в Key.Sign ()?
  • Как я могу сбросить открытый ключ в .Net?

Огонь, спасибо.

...