EMV 'recovery' function

145 views
Skip to first unread message

Larry

unread,
Feb 11, 2009, 4:35:16 PM2/11/09
to Crypto++ Users
I'm working with an EMV contactless card to use in our transit toll-
collection equipment. I'm somewhat familiar with 3DES but so far only
vaguely familiar with RSA/PKI. The EMV cards require two functions: a
'recovery' function and a hash (SHA-1) function. I'm assuming in time
I'll be able to figure out how to use CryptoPP for doing the hashing.
But I'm not quite clear on the 'recovery'. It is defined as
recovering data using a public key modulus 'n'=pq and a public key
exponent 'e' to recover the data 'X' from the signed data 'S' using:

X = Recover(Pk)[S]: = S^e mod n

I'm assuming that's an RSA 'decrypt' using a public key. I've been
sent two files, one a .sep and the other a .hep and am told they are
the public key. I'm not sure how to get those into any CryptoPP
function. While I may initially be getting the key from disk in a
Windows environment, eventually I'll have to port CryptoPP to a
GreenHills compiler to run on an ARM and the key will then be supplied
to me as a byte array in memory.

Obviously I'm at the very beginning of this and just starting to learn
things. But I'd be surprised if I'm the first person trying to do
this and was hoping someone might have some sample CryptoPP code that
would help me get started with this. Thanks for any help anyone can
give me!

Jeffrey Walton

unread,
Feb 11, 2009, 7:18:25 PM2/11/09
to Larry, Crypto++ Users
Hi Larry,

> The EMV cards require two functions: a
> 'recovery' function and a hash (SHA-1) function.

Protocol design questions are usually asked on the Usenet group sci.crypt.

> But I'm not quite clear on the [RSA] 'recovery'.
You will need a clarification here. There are two flavors of RSA
signatures. Those with Appendix, and those with Recovery. A signature
with Appendix requires that both the signature and message be
presented to the Verifier function. Recovery interleaves the original
message into the signature by using a Redundancy Function. (If
designing the system, questions are again 'best asked' on sci.crypt).
So a recovery system only presents the signature.

> It is defined as... X = Recover(Pk)[S]: = S^e mod n
It sounds like you are describing Recovery. But the notation appears
incorrect - it appears more like Appendix.

> I'm assuming that's an RSA 'decrypt' using a public key.

Hmmm... Sounds more like a verification to me. Similar to 'Encrypt
with private key' - which is not a valid cryptographic operation.
Sorry to split hairs.

> I've been sent two files, one a .sep and the other a .hep
> and am told they are the public key.

You will need a clarification here. I'm only aware of a single public
key representation, even in systems such as multi-prime RSA. So I'm
not sure why you have been given two public keys.

Finally, you'll need to know the format of the key. The best case for
you is probably an X.509 encoding since most of the free world is
equipped to work with it. If this is the case, feed it to Guttman's
dumpasn1 or Objective System's ASN1View
(http://www.obj-sys.com/asn1-viewer.php). Microsoft throws a curve
ball in its managed code by using RFC 3275 to format its keys. And the
worst case for you is a proprietary format.

> I've been sent two files, one a .sep and the other a .hep
> and am told they are the public key.

[Let's revisit] If the .sep is the signature and .hep is the public
key, you most likely have signature with appendix since you must
present both the signature and key to the verifier function.

> eventually I'll have to port CryptoPP to a
> GreenHills compiler to run on an ARM

If successful, please share with Wei and the group. This may prove
useful to others. Also not that Dr. Ugo Chirico maintains a Windows CE
port at http://www.ugosweb.com/cryptopp.aspx. It may prove useful
since Windows CE is targeted for the ARM [IV?] processor - you can
compare code generation when things go wrong in GreenHill.

> Obviously I'm at the very beginning of this and just

> starting to learn things...
From the, "I'm not quite clear on the 'recovery'", I'll assume you
want to know how to perform a verification in a recovery system.
Unfortunately neither the Wiki or CodeProject have any 'RSA Signature
with Recovery'* samples. CodeProject has a RSA Signatures, Part I
based on Appendix. Part II should be Recovery. It is clear the fellow
who is writing the articles is dragging his ass.

I am also not clear on Wei's implementation (I suspect I am missing a
detail). In rsa.h, Crypto++ offers:

// The three RSA signature schemes defined in PKCS #1 v2.0
typedef RSASS<PKCS1v15, SHA>::Signer RSASSA_PKCS1v15_SHA_Signer;
typedef RSASS<PKCS1v15, SHA>::Verifier RSASSA_PKCS1v15_SHA_Verifier;

In a Signature Scheme with Recovery, I believe the first template
argument (STANDARD in the source) should be PSSR rather than PKCS 1.
However, I do not see the Crypto++ source code using it. I would
expect the source to use it for benchmarks and validations (gotta love
self documenting code :).

Jeff

* http://www.cryptopp.com/wiki/RSA#RSA_Signature
* http://www.codeproject.com/KB/cpp/RsaSignatureAppendix.aspx

Jeffrey Walton

unread,
Feb 11, 2009, 8:49:39 PM2/11/09
to Larry, Crypto++ Users
Hi Larry,

My bad. The sample is actually there on the wiki. See RSA Probablistic
Signature Scheme with Recovery. I reprocuded it below with a few extra
comments for you.

Jeff

#include "osrng.h"
using CryptoPP::AutoSeededRandomPool;

#include "rsa.h"
using CryptoPP::RSA;
using CryptoPP::RSASS;
using CryptoPP::InvertibleRSAFunction;

#include "pssr.h"
using CryptoPP::PSSR;

#include "sha.h"
using CryptoPP::SHA;

#include "secblock.h"
using CryptoPP::SecByteBlock;

#include "cryptlib.h"
using CryptoPP::DecodingResult;

#include <iostream>
using std::cout;
using std::cerr;

#include <string>
using std::string;

typedef RSASS<PSSR, SHA>::Signer RSAPSSR_Signer;
typedef RSASS<PSSR, SHA>::Verifier RSAPSSR_SHA_Verifier;

int main(int argc, char* argv[])
{
AutoSeededRandomPool prng;

// Private Key. A Public Key can be derived
// from the private key.
InvertibleRSAFunction key;
key.GenerateRandomWithKeySize( prng, 1024 );

// Signer and Verifier
RSAPSSR_Signer signer( key );
RSAPSSR_SHA_Verifier verifier( signer );

// Because our message is 0x30 bytes in length, we need
// a modulus on the order of 1024. Otherwise we need an
// Exception Handler to catch the InvalidArgument
// exception which will be thrown.
byte message[] = "RSA Probablistic Signature Scheme with Recovery";
unsigned int messageLen = sizeof(message);

// Sign
SecByteBlock signature(signer.MaxSignatureLength(messageLen));

unsigned int signatureLen =
signer.SignMessageWithRecovery(prng, message, messageLen,
NULL, 0, signature);

/* ****************************** *\
\* ****************************** */

// Recover
SecByteBlock recovered(
verifier.MaxRecoverableLengthFromSignatureLength(signatureLen)
);

// Verify
DecodingResult result =
verifier.RecoverMessage(recovered, NULL, 0, signature, signatureLen);

if (!result.isValidCoding)
{
// Handle error
return -1;
}

unsigned int recoveredLen = result.messageLength;

// Place in a string for output
string m( (char*)(const byte*)recovered, recoveredLen );
cout << m << endl;

return 0;
}

> [ SNIP ]

Reply all
Reply to author
Forward
0 new messages