Problem with ECDSA secp256r1 OID

192 views
Skip to first unread message

Mariusz Kowalski

unread,
Dec 3, 2014, 4:08:55 AM12/3/14
to cryptop...@googlegroups.com
Hi!

I have a problem with PrivateKey format for ECDSA secp256r1 (NIST P-256,X9.62 prime256v1). I can generate it, save it, load it. Generally it seems to work good. But I can't use it in other libraries (like OpenSSL).

After some research I've found out, that it has wrong OID saved in file. It should have OID 1.2.840.10045.3.1.7 but it hasn't. Here is output from dumpasn1 for generated key:

  0 283: SEQUENCE {
 
4   1:   INTEGER 0
 
7 236:   SEQUENCE {
 
10   7:     OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1)
 
19 224:     SEQUENCE {
 
22   1:       INTEGER 1
 
25  44:       SEQUENCE {
 
27   7:         OBJECT IDENTIFIER prime-field (1 2 840 10045 1 1)
 
36  33:         INTEGER
       
:           00 FF FF FF FF 00 00 00 01 00 00 00 00 00 00 00
       
:           00 00 00 00 00 FF FF FF FF FF FF FF FF FF FF FF
       
:           FF
       
:         }
 
71  68:       SEQUENCE {
 
73  32:         OCTET STRING
       
:           FF FF FF FF 00 00 00 01 00 00 00 00 00 00 00 00
       
:           00 00 00 00 FF FF FF FF FF FF FF FF FF FF FF FC
107  32:         OCTET STRING
       
:           5A C6 35 D8 AA 3A 93 E7 B3 EB BD 55 76 98 86 BC
       
:           65 1D 06 B0 CC 53 B0 F6 3B CE 3C 3E 27 D2 60 4B
       
:         }
141  65:       OCTET STRING
       
:         04 6B 17 D1 F2 E1 2C 42 47 F8 BC E6 E5 63 A4 40
       
:         F2 77 03 7D 81 2D EB 33 A0 F4 A1 39 45 D8 98 C2
       
:         96 4F E3 42 E2 FE 1A 7F 9B 8E E7 EB 4A 7C 0F 9E
       
:         16 2B CE 33 57 6B 31 5E CE CB B6 40 68 37 BF 51
       
:         F5
208  33:       INTEGER
       
:         00 FF FF FF FF 00 00 00 00 FF FF FF FF FF FF FF
       
:         FF BC E6 FA AD A7 17 9E 84 F3 B9 CA C2 FC 63 25
       
:         51
243   1:       INTEGER 1
       
:       }
       
:     }
246  39:   OCTET STRING, encapsulates {
248  37:     SEQUENCE {
250   1:       INTEGER 1
253  32:       OCTET STRING
       
:         97 39 1C 01 2A E9 4F A4 06 59 4D A1 73 3C 06 3F
       
:         BE 8D B5 38 A5 EC A4 4D 32 A1 E3 CA D4 A8 2B E4
       
:       }
       
:     }
       
:   }

0 warnings, 0 errors.

Code for key geneartion and saving function:
CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA1>::PrivateKey myPrivateKey;

bool SavePrivateKey(const string& filename) {
   
AutoSeededRandomPool prng;
    myPrivateKey
.Initialize( prng, CryptoPP::ASN1::secp256r1() );

   
if (!myPrivateKey.Validate( prng, 3 )) {
       
return false;
   
}

    myPrivateKey
.Save( FileSink( filename.c_str(), true /*binary*/ ).Ref() );
   
return true;
}

OS: CentOS 6.6
Crypto++ library version: 5.6.2-2.el6

Would be nice if somebody found a way to use Crypto++ ECDSA secp256r1 keys outside Crypto++ library, or use same keys from OpenSSL inside Crypto++.

Thanks in advance
Mario

Jeffrey Walton

unread,
Dec 13, 2014, 4:21:29 PM12/13/14
to cryptop...@googlegroups.com

I can't comment on the potential OID mismatch. The best I can tell, it looks OK. http://www.oid-info.com/cgi-bin/display?oid=1.2.840.10045.2.1&action=display

From my testing, I think some libraries expect a key with a named curve, rather than a key with the domain parameters enumerated as shown above. In the case of OpenSSL, it should read the key, but it will fail later when you try and use it in a web server with SSL_CTX_use_PrivateKey_file (cf., http://wiki.openssl.org/index.php/Elliptic_Curve_Cryptography#Named_Curves). So you should try with a named curve.

To write out the named curve, you have to SetEncodeAsOID(true) on the DL_GroupParameters_EC:

    ECDSA<ECP, SHA1>::PrivateKey myPrivateKey;
    ...
    myPrivateKey.AccessGroupParameters().SetEncodeAsOID(true);

The PEM Pack had similar problems (http://www.cryptopp.com/wiki/PEM_Pack). The relevant code from the PEM Pack is below.

Jeff

**********

void PEM_Save(BufferedTransformation& bt, const DL_GroupParameters_EC<ECP>& params)
{
    bool old = PEM_GetNamedCurve(params);
    PEM_SetNamedCurve(params, true);
   
    PEM_SaveParams(bt, params, SBB_EC_PARAMETERS_BEGIN, SBB_EC_PARAMETERS_END);
    PEM_SetNamedCurve(params, old);
}

template <class EC>
bool PEM_GetNamedCurve(const DL_GroupParameters_EC<EC>& params)
{
    return params.GetEncodeAsOID();
}

template <class EC>
void PEM_SetNamedCurve(const DL_GroupParameters_EC<EC>& params, bool flag)
{
    DL_GroupParameters_EC<EC>& pp = const_cast<DL_GroupParameters_EC<EC>&>(params);
    pp.SetEncodeAsOID(flag);
}

Reply all
Reply to author
Forward
0 new messages