I was hoping someone could help me with the PIV smart card standard.
I would like to authenticate the smart card by making it sign a PKCS#1 padded nonce with the previously generated RSA 1024-bit modulus Digital Signature Key 0x9C. Here is what the output of my test application looks like:
Requesting Signature
Sending: 0087069C867C84820081800001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00CB441C4A656E071F1FB9F31BC6AB1824324FB42780
Error: (6A80) Incorrect parameters in command data
And here is the breakdown:
00 - Not chained (chaining not required because message does not exceed max length)
87 - GENERAL AUTHENTICATE
06 - RSA 1024 Algorithm
9C - Digital Signature Key
86 - Length of data field
7C - Dynamic Authentication template identifier
84 - Length of dynamic authentication template
82 - Response
00 - Response length 0 (Response requested)
81 - Challenge
80 - Challenge length 128
0001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00CB441C4A656E071F1FB9F31BC6AB1824324FB427 - PKCS #1 padded 20-byte Nonce (Padded with OpenSSL RSA_padding_add_PKCS1_type_1)
80 - Expected response length (128 bytes)
I have also run tests using all of the different keys (having generated all of them successfully already) and using chained messages vs single part messages.
See further test data.
There was a bug with the PIV card applet loaded on my smart card. It will not sign any data that starts with 0x00. If you change the 0x00 to anything else (as long as the data as an integer is less than the modulus as an integer per requirement of the RSA algorithm) it will sign successfully. So of course this means these cards cannot sign any standard PKCS1 padded data :(
Thanks for the help
Related
after a very long research on the web, I'm still not able to find any code/algorithm that shows how the shared-key authentication works in WEP, and in particular how the response is computed.
The general concept is clear:
The mobile station (MB) sends a connect request to the access
point (AP).
The AP replies with a challenge
The MB encrypts this challenge (it has to prove to have the shared key) and sends it back to the AP
The AP verifies the cypher text and allows the access.
Now:
The challenge is 128 bytes.
How is the response computed? When opening in wireshark the traffic, the response is usually 136 bytes, meaning that the encryption includes also something else.
This should be something like:
RC4 ( IV + challenge + CRC32(challenge))
Where can I verify if this expression is the correct one?
Furthermore:
the IV is 6 Hex digit (so 3 bytes) meaning that maybe there is an extension of one byte. How is this extension computed?
the challenge is 128 bytes
is the CRC-32 computed on the challenge text only? Does it include also the IV?
Could you please refer to any official document where I can find the complete specification of the fields involved in the computation?
Thanks
Facebook app secret is a string of 32 characters (0-9, a-f) and thus it represents a 128 bits byte array. Facebook uses this as the key to generate signed request using HMAC-SHA256. Is this a correct usage? I thought HMAC-SHA256 should use 256 bits keys.
HMAC takes the HASH(key) and uses it as the key if the length of the key is greater than the internal block size of the hash. Thus, a key larger than the internal block size of the hash provides no better security than one of equal size. Shorter keys are zero padded to be equal to the internal block size of the hash as per the HMAC specification.
It's impossible to use a 128-bit key with HMAC-SHA-256. If you mean 128 bits padded out to 512 bits with zeroes, then it's probably alright for short-term authentication. I'd recommend at least 256 bits and ideally you would want to use something equal to the internal block size of the underlying hash.
The page says that the 256bit signature is derived from a payload (what facebook is signing) + your 128 bit salt.
So yes, it sounds like correct usage.
The secret 16 bytes (32 characters) isn't actually a key in the sense that it's used to encrypt and decrypt something. Rather, it's a bit of data (a salt) that is used to alter the result of the digital signature, by changing the input ever-so-slightly, so that only someone who knew the exact secret and the exact payload could have created the signature.
is it true that RSA encryption only can handle limited payload of data ? ... im confused with the theory ... theoretically there is no note regarding this ...
RSA encrypts a single message which has a length which is somewhat smaller than the modulus. Specifically, the message is first "padded", resulting in a sequence of bytes which is then interpreted as a big integer between 0 and n-1, where n is the modulus (a part of the public key) -- so the padded message cannot be longer than the modulus, which implies a strict maximum length on the raw message.
Specifically, with the most common padding scheme (PKCS#1 "old-style", aka "v1.5"), the padding adds at least 11 bytes to the message, and the total padded message length must be equal to the modulus length, e.g. 128 bytes for a 1024-bit RSA key. Thus, the maximum message length is 117 bytes. Note that the resulting encrypted message length has the same size than the modulus, so the encryption necessarily expands the message size by at least 11 bytes.
The normal way of using RSA for encrypted a big message (say, an e-mail) is to use an hybrid scheme:
A random symmetric key K is chosen (a raw sequence of, e.g., 128 to 256 random bits).
The big message is symmetrically encrypted with K, using a proper and efficient symmetric encryption scheme such as AES.
K is asymmetrically encrypted with RSA.
"Splitting" a big message into so many 117-byte blocks, each to be encrypted with RSA, is not normally done, for a variety of reasons: it is difficult to do it right without adding extra weaknesses; each block would be expanded by 11 bytes, implying a non-negligible total message size increase (network bandwidth can be a scarce resource); symmetric encryption is much faster.
In the basic RSA algorithm (without padding) which is not very secure the size of the message is limited to be smaller than the modulus.
To enhance the security of RSA you should use padding schemes as defined in PKCS1. Depending on the scheme you choose the size of the message can be significantly smaller than the modulus.
http://en.wikipedia.org/wiki/PKCS1
is it true that RSA encryption only can handle limited payload of data ? ... im confused with the theory ... theoretically there is no note regarding this ...
RSA encrypts a single message which has a length which is somewhat smaller than the modulus. Specifically, the message is first "padded", resulting in a sequence of bytes which is then interpreted as a big integer between 0 and n-1, where n is the modulus (a part of the public key) -- so the padded message cannot be longer than the modulus, which implies a strict maximum length on the raw message.
Specifically, with the most common padding scheme (PKCS#1 "old-style", aka "v1.5"), the padding adds at least 11 bytes to the message, and the total padded message length must be equal to the modulus length, e.g. 128 bytes for a 1024-bit RSA key. Thus, the maximum message length is 117 bytes. Note that the resulting encrypted message length has the same size than the modulus, so the encryption necessarily expands the message size by at least 11 bytes.
The normal way of using RSA for encrypted a big message (say, an e-mail) is to use an hybrid scheme:
A random symmetric key K is chosen (a raw sequence of, e.g., 128 to 256 random bits).
The big message is symmetrically encrypted with K, using a proper and efficient symmetric encryption scheme such as AES.
K is asymmetrically encrypted with RSA.
"Splitting" a big message into so many 117-byte blocks, each to be encrypted with RSA, is not normally done, for a variety of reasons: it is difficult to do it right without adding extra weaknesses; each block would be expanded by 11 bytes, implying a non-negligible total message size increase (network bandwidth can be a scarce resource); symmetric encryption is much faster.
In the basic RSA algorithm (without padding) which is not very secure the size of the message is limited to be smaller than the modulus.
To enhance the security of RSA you should use padding schemes as defined in PKCS1. Depending on the scheme you choose the size of the message can be significantly smaller than the modulus.
http://en.wikipedia.org/wiki/PKCS1
I'm trying to encrypt some date using a public key derived form the exchange key pair made with the CALG_RSA_KEYX key type. I determined the block size was 512 bits using cryptgetkeyparam KP_BLOCKLEN. It seems the maximum number of bytes I can feed cryptencrypt in 53 (424 bits) for which I get an encrypted length of 64 back. How can I determine how many bytes I can feed into cryptencrypt? If I feed in more than 53 bytes, the call fails.
RSA using the usual PKCS#1 v.1.5 mode can encrypt a message that is at most k-11 bytes, where k is the length of the modulus in bytes. So a 512 bit key can encrypt up to 53 bytes and a 1024 bit key can encrypt up to 117 bytes.
RSA using OAEP can encrypt a message up to k-2*hLen-2, where k is the modulus byte-length and hLen is the length of the output of the underlying hash-function. So using SHA-1, a 512 bit key can encrypt up to 22 bytes and a 1024 bit key can encrypt up to 86 bytes.
You should not normally use a RSA key to encrypt your message directly. Instead you should generate a random symmetric key (f.x. an AES key), encrypt your message with the symmetric key, encrypt the key with the RSA key and transmit both encryptions to the recipient. This is usually called hybrid encryption.
EDIT: Although this response is marked as accepted by the OP, please see Rasmus Faber response instead, as this is a much better response. Posted 24 hours later, Rasmus's response corrects factual errors,in particular a mis-characterization of OAEP as a block cipher; OAEP is in fact a scheme used atop PKCS-1's Encoding Primitive for the purpose of key-encryption. OAEP is more secure and puts an even bigger limit on the maximum message length, this limit is also bound to a hash algorithm and its key length.
Another shortcoming of the following reply is its failure to stress that CALG_RSA_KEYX should be used exclusively for the key exchange, after which transmission of messages of any length can take place with whatever symmetric key encryption algorithm desired. The OP was aware of this, he was merely trying to "play" with the PK, and I did cover that much, albeit deep in the the long remarks thread.
Fore the time being, I'm leaving this response here, for the record, and also as Mike D may want to refer to it, but do remark-me-in, if you think that it would be better to remove it altogether; I don't mind doing so for sake of clarity!
-mjv- Sept 29, 2009
Original reply:
Have you check the error code from GetLastError(), following cryptencrypt()'s false return?
I suspect it might be NTE_BAD_LEN, unless there's be some other issue.
Maybe you can post the code that surrounds your calling criptencryt().
Bingo, upon seeing the CryptEncrypt() call.
You do not seem to be using the RSAES w/ OAEP scheme, since you do not have the CRYPT_OAEP flag on. This OAEP scheme is a block cipher based upon RSAES. This latter encryption algorihtm, however, can only encrypt messages slightly less than its key size (expressed in bytes). This is due to the minimum padding size defined in PKCS#1; such padding helps protect the algorithm from some key attacks, I think the ones based on known cleartext).
Therefore you have three options:
use the CRYPT_OAEP in the Flag parameter to CryptEncrypt()
extend the key size to say 1024 (if you have control over it, beware that longer keys will increase the time to encode/decode...)
Limit yourself to clear-text messages shorter than 54 bytes.
For documentation purposes, I'd like to make note of a few online resources.
- The [RSA Labs][1] web site which is very useful in all things crypto.
- Wikipedia articles on the subject are also quite informative, easier to read
and yet quite factual (I think).
When in doubt, however, do consult a real crypto specialist, not someone like me :-)