On Mon, Sep 26, 2011, Clment Marcel wrote:

> Hello,
> 
> I have some problems to sign message with OpenSSL. The following code has
> been provided as an example (of a global project prototype):
> 
> input arguments are:
> * Bin: const unsigned char * to be signed
> * BinLen: length of the previous parameter
> 
> --- BEGIN OF CODE ---
> 
> // Initialization of engine to retrieve private key.
> UI_METHOD * ui_method = UI_OpenSSL();
> ENGINE    * engine    = ENGINE_by_id( "pkcs11" );
> ENGINE_init( engine );
> EVP_PKEY  * priv_key  = ( EVP_PKEY * ) ENGINE_load_private_key( engine,
> "0:01000000", ui_method, ( void * ) _password.c_str() );
> ENGINE_finish( engine );
> ENGINE_free( engine );
> 
> // Perfom signature with SHA1 hash function.
> EVP_PKEY_CTX * pkctx = EVP_PKEY_CTX_new( priv_key, NULL );
> size_t sltmp = EVP_PKEY_size( priv_key );
> unsigned char sigret[2048];
> EVP_PKEY_sign_init( pkctx );
> EVP_PKEY_CTX_set_signature_md( pkctx, EVP_get_digestbyname( "SHA1" ) );
> EVP_PKEY_CTX_set_rsa_padding( pkctx, RSA_PKCS1_PADDING );
> EVP_PKEY_sign( pkctx, sigret, & sltmp, Bin, BinLen );
> EVP_PKEY_CTX_free( pkctx );
> EVP_PKEY_free( priv_key );
> 
> // Return base 64 encoding string with base64Encode function.
> std::string res = base64Encode( sigret, sltmp );
> 
> --- END OF CODE ---
> 
> My problem is that this code part uses OpenSSL 1.0.0. We want use a similar
> code with an older version (0.9.8) that not implements theses functions. So,
> I try to perform the same actions with older functions, like this:
> 
> --- BEGIN OF CODE ---
> 
> // Initialization of engine to retrieve private key.
> UI_METHOD * ui_method = UI_OpenSSL();
> ENGINE    * engine    = ENGINE_by_id( "pkcs11" );
> ENGINE_init( engine );
> EVP_PKEY  * priv_key  = ( EVP_PKEY * ) ENGINE_load_private_key( engine,
> "0:01000000", ui_method, ( void * ) _password.c_str() );
> ENGINE_finish( engine );
> ENGINE_free( engine );
> 
> // Perfom signature with SHA1 hash function.
> EVP_MD_CTX      md_ctx;
> unsigned char sig_buf [2048];
> EVP_SignInit   ( & md_ctx, EVP_sha1() );
> EVP_SignUpdate ( & md_ctx, ( const char * ) Bin, strlen( ( const char * )
> Bin ) );
> size_t sig_len = sizeof( sig_buf );
> int    err     = EVP_SignFinal ( & md_ctx, sig_buf, & sig_len, priv_key );
> 
> // Return base 64 encoding string with base64Encode function.
> std::string res = base64Encode( sig_buf, sig_len );
> 
> --- END OF CODE ---
> 
> For the same private key (read from a smart card), I obtain the following
> results:
> 
> > message to be signed: "hello"
> > length: 5
> 
> > signature with first code: this value changes at each launch without
> recompilation (is there normal ?)
> 6O9oAzIEBDJQAWgDAABoAwAAaANQAWgDAACoAZulVndoIBcEwAQAAO7+7v4AAKgB2B8XBAAAAACaAASeGAQAAGAgFwRA/hYEuB0XBPgDAAB/AAAAPJeYAQAAqAH5q1Z36B8XBEAFAAB6OFF3q9fidwAAAAAAAKgB4B8XBPABBPVQAWgDAgAEBjjraAOiBwSh0KloA5YCAAAAAAAAUAGoAQAAqAF/AAAAUAGoAUD+FgTQVll3DJeYAdiWmAEGB1t3AABoAwAAAAB/AAAABAAAALq4UHcw62gDAABoA0D+FgS6uFB3+AMAAByXmAGwFlt38AEE9X8AAACL1+J3AABoAw==
> or
> 6O9VAzIEBDJQAVUDAABVAwAAVQNQAVUDAADsAZulVndoIAcEwAQAAO7+7v4AAOwB2B8HBAAAAACaAASeGAQAAGAgBwRA/gYEuB0HBPgDAAB/AAAAPJeYAQAA7AH5q1Z36B8HBEAFAAB6OFF3e5vjdwAAAAAAAOwB4B8HBPABBPVQAVUDAgAEBjjrVQOiBwSh0KlVA5YCAAAAAAAAUAHsAQAA7AF/AAAAUAHsAUD+BgTQVll3DJeYAdiWmAEGB1t3AABVAwAAAAB/AAAABAAAALq4UHcw61UDAABVA0D+BgS6uFB3+AMAAByXmAGwFlt38AEE9X8AAABbm+N3AABVAw==
> 
> > signature with second code: (don't change)
> OfXXJTi5mxNm9iSmDS9g/p/d1aw1C2E+nmBZs8TEsYdGm/5f8oSaTW40vvidMW+riXsM+ERTe0X8Z0QKgXPhc+sooN1b6E9ctx8IGN9V3yFN+fwaF2VY4U1RJIL+zSU7j6hZ8nx2iqUSzUKL19EH9J5p//MLfYawTU7mVXxGq0UFrrDVlvHw1ea/00IDGnzMY3yfJFuMAkxmLMUZnC6C8igc3SfwJlM+S6fEGwRrXGIlWLsy4q3cNxhDCsj+89+zweOVVYXTHlMyM8lvAVjI9yr7OPKflIDopmepvpzqCzgDU9oLpFfQBSjCSvYIRT6UJE4/x/TA3lpCFfZ7lDNyHg==
> 
> I use OpenSSL 1.0.0 on Microsoft Windows 7. We aim to use this function also
> on linux & Mac OS.
> 
> Have anybody an idea about this problem ? or how to properly port first code
> to < 1.0.0 OpenSSL library (and why the signature is changing at each run ?)
> 

Both sets of code are badly broken. They perform zero error checking which
means any kind of failure including hardware failure (not unknown for smart
cards) or invalid usage wont be caught.

If you added error checking to the first case I suspect you'd get a failure
because it is using the function incorrectly. It is passing a message to sign
into a function which is expecting the digest of that message. If that is the
wrong length it should return an error. That would explain getting a different
value each time: it is just outputing an unintialised buffer as the signing
function fails.

The second version is rather better apart from lack of error checking. It is
doing a digest and sign operation. That version should work fine in 1.0.0.

Steve.
--
Dr Stephen N. Henson. OpenSSL project core developer.
Commercial tech support now available see: http://www.openssl.org
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    openssl-users@openssl.org
Automated List Manager                           majord...@openssl.org

Reply via email to