RSA Algorithm
RSA Algorithm
The RSA algorithm is named after Ron Rivest, Adi Shamir and Len Adleman, who invented it in 1977 [RIVE78]. The basic technique was first discovered in 1973 by Clifford Cocks [COCK73] of CESG (part of the British GCHQ) but this was a secret until 1997. The patent taken out by RSA Labs has expired. The RSA cryptosystem is the most widely- used public key cryptography algorithm in the world. It can be used to encrypt a message without the need to exchange a secret key separately. The RSA algorithm can be used for both public key encryption and digital signatures. Its secur ity is based on the difficulty of factoring large integers. Party A can send an encrypted message to party B without any prior exchange of secret keys. A just uses B's public key to encrypt the message and B decrypts it using the private key, which only he knows. RSA can also be used to sign a message, so A can sign a message using their private key and B can verify it using A's public key. We look into the mathematics behind the algorithm on our RSA Theory page completely re-written. 2011-11-03:
Contents
Key generation algorithm Encryption Decryption Digital signing Signature verification Notes on practical application Summary of RSA Theory and proof of the RSA algorithm Key length Computational efficiency and the Chinese Remainder Theorem A very simple example A slightly less simple example A real example PKCS#1 Schemes o Encryption using PKCS#1v1.5 o Signing using PKCS#1v1.5 Weaknesses in RSA More Advanced Schemes o RSAES-OAEP o RSASSA-PSS
ANSI X9.31 Signature Scheme ISO/IEC 9796 RSA-KEM Ferguson-Schneier Encryption Notation and Conventions What is the difference between a bit string and an integer? Implementation in C and VB References Author Contact Comments
o o o o
Encryption
Sender A does the following:1. 2. 3. 4. Obtains the recipient B's public key (n, e). Represents the plaintext message as a positive integer m , 1 < m < n [see note 4]. Computes the ciphertext c = me mod n. Sends the ciphertext c to B.
Decryption
Recipient B does the following:1. Uses his private key (n, d) to compute m = c d mod n. 2. Extracts the plaintext from the message representative m .
Digital signing
Sender A does the following:1. 2. 3. 4. Creates a message digest of the information to be sent. Represents this digest as an integer m between 1 and n-1. [See note 5]. Uses her private key (n, d) to compute the signature s = md mod n. Sends this signature s to the recipient, B.
Signature verification
Recipient B does the following:1. 2. 3. 4. Uses sender A's public key (n, e) to compute integer v = se mod n. Extracts the message digest from this integer. Independently computes the message digest of the information that has been signed. If both message digests are identical, the signature is valid.
2010-08-14: For more details of the extended Euclidean algorithm, see our new page The Euclidean Algorithm and the Extended Euclidean Algorithm which shows how to use the Euclidean algorithm, answer exam questions on it, and gives source code for an implementation. 4. When representing the plaintext octets as the representative integer m , it is usual to add random padding characters to make the size of the integer m large and less susceptible to certain types of attack. If m = 0 or 1 or n-1 there is no security as the ciphertext has the same value. For more details on how to represent the plaintext octets as a suitable representative integer m, see PKCS#1 Schemes below or the reference itself [PKCS1]. It is important to make sure that m < n otherwise the algorithm will fail. This is usually done by making sure the first octet of m is equal to 0x00. 5. Decryption and signing are identical as far as the mathematics is concerned as both use the private key. Similarly, encryption and verification both use the same mathematical operation with the public key. That is, mathematically, for m < n, m = (me mod n)d mod n = (md mod n)e mod n However, note these important differences in implementation:The signature is derived from a message digest of the original information. The recipient will need to follow exactly the same process to derive the message digest, using an identical set of data. o The recommended methods for deriving the representative integers are different for encryption and signing (encryption involves random padding, but signing uses the same padding each time). 6. The original definition of RSA uses the Euler totient function (n) = (p-1)(q-1). More recent standards use the Charmichael function (n) = lcm(p-1, q- 1) instead. (n) is smaller than (n) and divides it. The value of d' computed by d' = e -1 mod (n) is usually different from that derived by d = e-1 mod (n), but the end result is the same. Both d and d' will decrypt a message me mod n and both will give the same signature value s = md mod n = md' mod n. To compute (n), use the relation
o 7. (n) = (p-1)(q-1) / gcd(p-1, q-1).
Summary of RSA
n = pq, where p and q are distinct primes. phi, = (p-1)(q-1) e < n such that gcd(e, phi)=1 d = e-1 mod phi. c = me mod n, 1<m<n. m = cd mod n. For more on the theory and mathematics behind the algorithm, see the RSA Theory page.
Key length
When we talk about the key length of an RSA key, we are referring to the length of the modulus, n, in bits. The minimum recommended key length for a secure RSA transmission is currently 1024 bits. A key length of 512 bits is now no longer considered secure, although cracking it is still not a trivial task for the likes of you and me. The longer your information is needed to be kept secure, the longer the key you should use. Keep up to date with the latest recommendations in the security journals. There is small one area of confusion in defining the key length. One convention is that the key length is the position of the most significant bit in n that has value '1', where the least significant bit is at position 1. Equivalently, key length = ceiling(log2 (n+1)). The other convention, sometimes used, is that the key length is the number of bytes needed to store n multiplied by eight, i.e. ceiling(log256 (n+1))*8. The key used in the RSA Example paper [KALI93] is an example. In hex form the modulus is
0A C0 D0 01 66 01 53 14 79 C6 B3 A1 1D 27 E3 DF C6 10 78 E6 98 27 2A 7C 81 00 1D DC 68 75 E5 9A DE 14 DC 9A 7A 29 5A F5 B7 42 F4 5D 74 E1 EB 65 19 9A E9 56 BB 8D 94 20 7F 8C 68 BB B0 51 17 AB
The most significant byte 0x0A in binary is 00001010'B. The most significant bit is at position 508, so its key length is 508 bits. On the other hand, this value needs 64 bytes to store it, so the key length could also be referred to by some as 64 x 8 = 512 bits. We prefer the former method. You can get into difficulties with the X9.31 method for signatures if you use the latter convention.
Note just how huge (and impractical) an RSA key needs to be for comparable security with AES192 or AES-256 (although these two algorithms have had some weaknesses exposed recently; AES-128 is unaffected).
The above table is a few years old now and may be out of date. Existing cryptographic algorithms only get weaker as attacks get better.
The time to carry out modular exponentation increases with the number of bits set to one in the exponent e. For encryption, an appropriate choice of e can reduce the computational effort required to carry out the computation of c = me mod n. Popular choices like 3, 17 and 65537 are all primes with only two bits set: 3 = 0011'B, 17 = 0x11, 65537 = 0x10001. The bits in the decryption exponent d, however, will not be so convenient and so decryption using the standard method of modular exponentiation will take longer than encryption. Don't make the mistake of trying to contrive a small value for d; it is not secure. An alternative method of representing the private key uses the The Chinese Remainder Theorem (CRT). 2011-01-20: For an explanation of how the CRT is used with RSA, see Using the CRT with RSA. The private key is represented as a quintuple (p, q, dP, dQ, and qInv), where p and q are prime factors of n, dP and dQ are known as the CRT exponents, and qInv is the CRT coefficient . The CRT method of decryption is about four times faster overall than calculating m = cd mod n. The extra values for the private key are:dP = (1/e) mod (p-1)
where the (1/e) notation means the modular inverse (see note 3 above). These values are precomputed and saved along with p and q as the private key. To compute the message m given c do the following:m1 = c^dP mod p m2 = c^dQ mod q h = qInv(m1 - m2) mod p m = m2 + hq
Even though there are more steps in this procedure, the modular exponentation to be carried out uses much shorter exponents and so it is less expensive overall. [2008-09-02] Chris Becke has pointed out that most large integer packages will fail when computing h if m1 < m2. This can be easily fixed by computing
h = qInv(m1 + p - m2) mod p
This is actually the smallest possible value for the modulus n for which the RSA algorithm works. Now say we want to encrypt the message m = 7, c = me mod n = 73 mod 33 = 343 mod 33 = 13. Hence the ciphertext c = 13. To check decryption we compute m' = c d mod n = 137 mod 33 = 7. Note that we don't have to calculate the full value of 13 to the power 7 here. We can make use of the fact that a = bc mod n = (b mod n).(c mod n) mod n so we can break down a potentially large number into its components and combine the results of easier, smaller calculations to calculate the final value. One way of calculating m' is as follows:Note that any number can be expressed as a sum of powers of 2. So first compute values of 132 , 134 , 138 , ... by repeatedly squaring successive values modulo 33. 132 = 169 4, 134 = 4.4 = 16, 138 = 16.16 = 256 25. Then, since 7 = 4 + 2 + 1, we have m' = 13 7 = 13(4+2+1) = 134 .132 .131 16 x 4 x 13 = 832 7 mod 33 Now if we calculate the ciphertext c for all the possible values of m (0 to 32), we get
m c 0 0 1 1 2 3 4 5 6 7 8 8 27 31 26 18 13 17 9 10 11 12 13 14 15 16 3 10 11 12 19 5 9 4
m 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 c 29 24 28 14 21 22 23 30 16 20 15 7 2 6 25 32
Note that all 33 values of m (0 to 32) map to a unique code c in the same range in a sort of random manner. In this case we have nine values of m that map to the same value of c - these are known as unconcealed messages. m = 0, 1 and n-1 will always do this for any n, no matter how large. But in practice, higher values shouldn't be a problem when we use large values for n in the order of several hundred bits. If we wanted to use this system to keep secrets, we could let A=2, B=3, ..., Z=27. (We specifically avoid 0 and 1 here for the reason given above). Thus the plaintext message "HELLOWORLD" would be represented by the set of integers m1 , m2 , ...
(9,6,13,13,16,24,16,19,13,5)
Note that this example is no more secure than using a simple Caesar substitution cipher, but it serves to illustrate a simple example of the mechanics of RSA encryption. Remember that calculating me mod n is easy, but calculating the inverse c-e mod n is very difficult, well, for large n's anyway. However, if we can factor n into its prime factors p and q,
the solution becomes easy again, even for large n's. Obviously, if we can get hold of the secret exponent d, the solution is easy, too.
In the same way that a decimal number can be represented as the sum of powers of ten, e.g. 135 = 1 x 102 + 3 x 101 + 5, we could represent our blocks of three characters in base 26 using A=0, B=1, C=2, ..., Z=25 ATT ACK XAT XSE VEN = = = = = 0 x 26 2 + 19 x 261 + 19 = 513 0 x 26 2 + 2 x 26 1 + 10 = 62 23 x 262 + 0 x 261 + 19 = 15567 23 x 262 + 18 x 26 1 + 4 = 16020 21 x 262 + 4 x 261 + 13 = 14313
For this example, to keep things simple, we'll not worry about numbers and punctuation characters, or what happens with groups AAA or AAB. In this system of encoding, the maximum value of a group (ZZZ) would be 26 3 -1 = 17575, so we require a modulus n greater than this value. 1. We "generate" primes p=137 and q=131 (we cheat by looking for suitable primes around n) 2. n = pq = 137.131 = 17947 phi = (p-1)(q-1) = 136.130 = 17680 3. Select e = 3 check gcd(e, p-1) = gcd(3, 136) = 1, OK and check gcd(e, q-1) = gcd(3, 130) = 1, OK. 4. Compute d = e-1 mod phi = 3-1 mod 17680 = 11787. 5. Hence public key, (n, e) = (17947, 3) and private key (n, d) = (17947, 11787). Question: Why couldn't we use e=17 here? To encrypt the first integer that represents "ATT", we have c = me mod n = 5133 mod 17947 = 8363. We can verify that our private key is valid by decrypting m' = c d mod n = 836311787 mod 17947 = 513. Overall, our plaintext is represented by the sequence of integers m
(513, 62, 15567, 16020, 14313)
We compute corresponding ciphertext integers c = me mod n, (which is still possible by using a calculator) and send this to the person who has the private key.
(8363, 5017, 11884, 9546, 13366)
You are welcome to compute the inverse of these ciphertext integers using m = c d mod n to verify that the RSA algorithm still holds. However, this is now outside the realms of hand calculations unless you are very patient. To help you carry out these modular arithmetic calculations, download our free modular arithmetic command line programs (last updated 18 June 2009). Note that this is still a very insecure example. Starting with the knowledge that the modulus 17947 is probably derived from two prime numbers close to its square root, a little testing of suitable candidates from a table of prime numbers will get you the answer pretty quickly. 17947 = 133.97, so working downwards from a table of prime numbers we try: 131: 17947 / 131 = 137 exactly, so we have it. You could also write a simple computer program to factor n that just divides by every odd number starting from 3 until it reaches a number greater than the square root of n.
A real example
In practice, we use a modulus of size in the order of 1024 bits. That is over 300 decimal digits. One example is
n = 11929413484016950905552721133125564964460656966152763801206748195494305685115 033 38063159570377156202973050001186287708466899691128922122454571180605749959895 170 80042105263427376322274266393116193517839570773505632231596681121927337473973 220 312512599061231322250945506260066557538238517575390621262940383913963
With a number this large, we can encode all the information we need in one big integer. We put our message into an octet string and then convert to a large integer. Also, rather than trying to represent the plaintext as an integer directly, we generate a random session key and use that to encrypt the plaintext with a conventional, much faster symmetrical algorithm like Triple DES or AES-128. We then use the much slower public key encryption algorithm to encrypt just the session key. The sender A then transmits a message to the recipient B in a format something like this:-
Session key encrypted with RSA = xxxx Plaintext encrypted with session key = xxxxxxxxxxxxxxxxx
The recipient B would extract the encrypted session key and use his private key (n,d) to decrypt it. He would then use this session key with a conventional symmetrical decryption algorithm to decrypt the actual message. Typically the transmission would include in plaintext details of the encryption algorithms used, padding and encoding methods, initialisation vectors and other details required by the recipient. The only secret required to be kept, as always, should be the private key. If Mallory intercepts the transmission, he can either try and crack the conventionally-encrypted plaintext directly, or he can try and decrypt the encryped session key and then use that in turn. Obviously, this system is as strong as its weakest link. When signing, it is usual to use RSA to sign the message digest of the message rather than the message itself. A one-way hash function like SHA-1 or SHA-256 is used. The sender A then sends the signed message to B in a format like this
Hash algorithm = hh Message content = xxxxxxxxx...xxx Signature = digest signed with RSA = xxxx
The recipient will decrypt the signature to extract the signed message digest, m; independently compute the message digest, m', of the actual message content; and check that m and m' are equal. Putting the message digest algorithm at the beginning of the message enables the recipient to compute the message digest on the fly while reading the message.
PKCS#1 Schemes
The most common scheme using RSA is PKCS#1 version 1.5 [PKCS1]. This standard describes schemes for both encryption and signing. The encryption scheme PKCS#1v1.5 has some known weaknesses, but these can easily be avoided. See Weaknesses in RSA below. There is an excellent paper by Burt Kalinski of RSA Laboratories written in the early 1990s [KALI93] that describes in great detail everything you need to know about encoding and signing using RSA. There are full examples right down to listing out the bytes. OK, it uses MD2 and a small 508-bit modulus and obviously doesn't deal with refinements built up over the last decade to deal with more subtle security threats, but it's an excellent introduction. The conventions we use here are explained below in Notation and Conventions.
where || denotes concatenation and PS is a string of k-|D|-3 non- zero randomlygenerated bytes (i.e. at least eight random bytes). 3. Convert the byte string, EB, to an integer, m, most significant byte first,
4. 6. 8. m = StringToInteger(EB) c = m^e mod n OB = IntegerToString(m, k)
5. Encrypt with the RSA algorithm 7. Convert the resulting ciphertext, c, to a k -byte output block, OB 9. Output OB.
The conversions in steps (2) and (4) from byte string to large integer representative and back again may not be immediately obvious. Large integers and byte (bit) strings are conceptually different even though they may both be stored as arrays of bytes in your computer. See What is the difference between a bit string and an integer?
Worked Example
Bob's 1024-bit RSA encryption key in hex format:
n=
The encoded message block, EB, after encoding but before encryption, with random padding bytes shown in green,
0002257F48FD1F1793B7E5E02306F2D3228F5C95ADF5F31566729F132AA12009 E3FC9B2B475CD6944EF191E3F59545E671E474B555799FE3756099F044964038 B16B2148E9A2F9C6F44BB5C52E3C6C8061CF694145FAFDB24402AD1819EACEDF 4A36C6E4D2CD8FC1D62E5A1268F496004E636AF98E40F3ADCFCCB698F4E80B9F
The above hex data in C format. Note that the output for encryption will be different each time (or should be!) because of the random padding used.
Encrypting a message
For a plaintext message, say,
PT="Hello world!"
the ciphertext using AES-128 in CBC mode with PKCS padding is,
CT=67290EF00818827C777929A56BC3305B
The sender would then send a transmission to the recipient (in this case, Bob) including the following information in some agreed format
Recipient: Bob Key Encryption Algorithm: rsaEncryption Encrypted Key: 3D2AB25B1EB667A40F504CC4D778EC399A899C8790EDECEF062CD739492C9CE5 8B92B9ECF32AF4AAC7A61EAEC346449891F49A722378E008EFF0B0A8DBC6E621
EDC90CEC64CF34C640F5B36C48EE9322808AF8F4A0212B28715C76F3CB99AC7E 609787ADCE055839829E0142C44B676D218111FFE69F9D41424E177CBA3A435B Content Encryption Algorithm: aes128-cbc IV: 5732164B3ABB6C4969ABA381C1CA75BA Encrypted Content: 67290EF00818827C777929A56BC3305B
The usual formats used for such a message are either a CMS enveloped-data object or XML, but the above summary includes all the necessary info (well, perhaps "Bob" might be defined a bit more accurately). Cryptographic Message Syntax (CMS) [CMS] is a less-ambiguous version of the earlier PKCS#7 standard (also of the same name) and is designed to be used in S/MIME messages. CMS enveloped-data objects (yes, that's enveloped not encrypted) use ASN.1 and are encoded using either DER- or BER-encoding. (DER-encoding is a stricter subset of BER). The terminology for CMS and ASN.1 may sound messy, but the end results are well-defined and universally- accepted. On the other hand, the XML cryptographic standards are, to be honest, a complete mess: see XML is xhite. Pretty Good Privacy (PGP) also has a format for RSA messages, although PGP stopped using RSA because of patent issues back in the 1990s. Nothing, of course, stops you and your recipient from agreeing on your own format and using that. But be careful, even the experts get these things wrong and accidentally give away more than they realise.
3. Form the byte string, T, from the message digest, H, according to the message digest algorithm, Hash, as follows Hash 30 MD5 SHA-1 30 SHA-256 30 SHA-384 30 T
20 30 0c 06 08 2a 86 48 86 f7 0d 02 05 05 00 04 10 || H 21 30 09 06 05 2b 0e 03 02 1a 05 00 04 14 || H 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20 || H 41 30 0d 06 09 60 86 48 01 65 03 04 02 02 05 00 04 30 || H
SHA-512 30 51 30 0d 06 09 60 86 48 01 65 03 04 02 03 05 00 04 40 || H 4. where T is an ASN.1 value of type DigestInfo encoded using the Distinguished Encoding Rules (DER). 5. Form the k -byte encoded message block, EB,
6. EB = 00 || 01 || PS || 00 || T
where || denotes concatenation and PS is a string of bytes all of value 0xFF of such length so that |EB|=k. 7. Convert the byte string, EB, to an integer m, most significant byte first,
8. 10. 12. m = StringToInteger(EB) s = m^d mod n OB = IntegerToString(s, k)
9. Sign with the RSA algorithm 11. Convert the resulting signature value, s, to a k -byte output block, OB 13. Output OB.
Worked Example
Alice's 1024-bit RSA signing key in hex format:
n= E08973398DD8F5F5E88776397F4EB005BB5383DE0FB7ABDC7DC775290D052E6D 12DFA68626D4D26FAA5829FC97ECFA82510F3080BEB1509E4644F12CBBD832CF C6686F07D9B060ACBEEE34096A13F5F7050593DF5EBA3556D961FF197FC981E6 F86CEA874070EFAC6D2C749F2DFA553AB9997702A648528C4EF357385774575F e=010001 d= 00A403C327477634346CA686B57949014B2E8AD2C862B2C7D748096A8B91F736 F275D6E8CD15906027314735644D95CD6763CEB49F56AC2F376E1CEE0EBF282D F439906F34D86E085BD5656AD841F313D72D395EFE33CBFF29E4030B3D05A28F B7F18EA27637B07957D32F2BDE8706227D04665EC91BAF8B1AC3EC9144AB7F21
The encoded message block, EB, after encoding but before signing is
0001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00302130 0906052B0E03021A05000414A9993E364706816ABA3E25717850C26C9CD0D89D
Weaknesses in RSA
Small encryption exponent If you use a small exponent like e=3 and send the same message to different recipients and just use the RSA algorithm without adding random padding to the message, then an eavesdropper could recover the plaintext. 2010-10-23: For an example of this, see Cracking RSA on our page on the The Chinese Remainder Theorem. Using the same key for encryption and signing Given that the underlying mathematics is the same for encryption and signing, only in reverse, if an attacker can convince a key holder to sign an unformatted encrypted message using the same key then she gets the original. Acting as an oracle There are techniques to recover the plaintext if a user just blindly returns the RSA transformation of the input. So don't do that.
Solutions
1. 2. 3. 4. 5. Don't use the same RSA key for encryption and signing. If using PKCS#v1.5 encoding, use e=0x10001 for your public exponent. Always format your input before encrypting or signing. Always add fresh random padding - at least 8 bytes - to your message before encrypting. When decrypting, check the format of the decrypted block. If it is not as expected, return an error, not the decrypted string. 6. Similarly, when verifying a signature, if there is any error whatsoever, just respond with "Invalid Signature".
RSAES-OAEP
The OAEP encoding technique for encryption is described in PKCS#1 version 2 and in IEEE P136. It is more secure than the PKCS#1v1.5 encoding method described above, perhaps provably secure. The encoding technique involves a mask generation function (MGF) based on a hash function and there is no obvious structure in the encoded block, unlike the PKCS#1v1.5 encoding method. Despite being the recommended method for the last decade, OAEP is not used in practice as much as you'd expect. In fact, hardly at all.
RSASSA-PSS
The PSS encoding method is used to encode before creating a signature. The technique is described in PKCS#1v2.1 and is similar in design to the OAEP encoding used for encryption involving an MGF based on a hash function. However, there are active patents associated with this method, so sensible implementors avoid it like the plague. Since there are currently no known weaknesses with the PKCS#1v1.5 signature scheme and the nasty smell of patents still lingers, PSS is also not used in practice very much.
where PS is a string of bytes all of value 0xBB of length such that |EB|=|n|, and 0x33 is the ISO/IEC 10118 part number for SHA-1. The byte string, EB, is converted to an integer value, the message representative, f .
Algorithm: Forming an X9.31/RSA2 signature value from the message representative (for odd e). INPUT: Signer's RSA private key, (n, d); integer, f , where 0 <= f < n and f 12 (mod 16). OUTPUT: Signature, an integer s, 0 <= s < n/2, i.e. a value at least one bit shorter than n. 1. t = fd mod n 2. s = min{t, n-t} 3. Output s.
Algorithm: Extracting the message representative from an X9.31/RSA2 signature value (for odd e). INPUT: Signer's RSA public key, (n, e); signature, s. OUTPUT: Message representative, f , such that t 12 (mod 16), or "invalid signature". 1. 2. 3. 4. 5. If s is not in [0,(n-1)/2], output "invalid signature" and stop. Compute t = se mod n If t 12 (mod 16) then let f = t. Else let f = n-t. If NOT f 12 (mod 16), output "invalid signature" and stop. Output f .
The integer f is converted to a byte string of length |n| bytes and then parsed to confirm that all bytes match the required format
EB = 06 || PS || 0xBA || H || 0x33 || 0xCC
If not, output "invalid signature" and stop; otherwise output the extracted message digest hash, H.
ISO/IEC 9796
IOS/IEC 9796 is an old standard devised before there was a recognised message digest function like MD5 or SHA-1. It allows the entire message to be recovered. Unfortunately, it is considered broken for signing plain text messages, but is still OK for signing message digest values. It is used in the AUTACK scheme described in [EDIFACT]. The encapsulation mechanism weaves the input bytes into a format exactly one bit shorter than the RSA key. The signing mechanism is similar to that in ANSI X9.31 described above, but the message representative, f , is required to be f 6 (mod 16), instead of modulo 12. In other words, make sure the last 4 bits are equal to 0x6 instead of 0xC.
RSA-KEM
The RSA-KEM Key Transport Algorithm encrypts a random integer with the recipient's public key, and then uses a symmetric key-wrapping scheme to encrypt the keying data. KEM stands for Key Encapsulation Mechanism . The general algorithm is as follows 1. 2. 3. 4. 5. Generate a random integer z between 0 and n-1. Encrypt the integer z with the recipient's RSA public key: c = ze mod n. Derive a key-encrypting key KEK from the integer z. Wrap the keying data using KEK to obtain wrapped keying data WK. Output c and WK as the encrypted keying data.
This method has a higher security assurance than PKCS#1v1.5 because the input to the underlying RSA operation is random and independent of the message, and the key-encrypting key KEK is derived from it in a strong way. The downside is that you need to implement a key
derivation method (of which there are many varieties - see How many KDFs are there?) and a key wrapping algorithm. The encoding of the final data into the recommended ASN.1 format is messy, too. For more details, see [CMSRSAKEM]. We published our own set of test vectors for RSA-KEM in January 2008 (now out of date).
Ferguson-Schneier Encryption
In their book [FERG03], Niels Ferguson and Bruce Schneier suggest a much simpler method of encryption. They suggest using the same modulus n for both encryption and signatures but to use e=3 for signatures and e=5 for encryption. They use RSA to encrypt a random integer and use a hash function to derive the actual content encryption key, thus removing any structural similarities between the actual CEK and the data encrypted by the RSA. F&S recommend using the function, Hash(x):=SHA256(SHA256(x)), for hashing data.
Algorithm: Ferguson-Schneier Encrypt Random Key with RSA. INPUT: Recipient's RSA public key, (n, e). OUTPUT: Content encryption key, CEK; RSA-encrypted CEK, c. 1. 2. 3. 4. 5. Compute the exact bit length of the RSA key, k = ceiling(log2 (n+1)). Choose a random r in the interval [0, 2k -1]. Compute the content encryption key by hashing r, CEK=Hash(r). c = re mod n. Output CEK and c.
For a plaintext message, m, the transmission sent to the recipient is IntegerToString(c) || ECEK(m), where ECEK(m) is the result of encrypting m with a symmetrical encryption algorithm using key, CEK. Given that the recipient knows the size of the RSA key and hence the exact number of bytes needed to encode c, it is a simple matter to parse the input received from the sender. For example code of this algorithm in Visual Basic (both VB6 and VB.NET) using our CryptoSys PKI Toolkit, see Ferguson-Schneier RSA Encryption.
IntegerToString(i, n) is an n-byte encoding of the integer i with the most significant byte first (i.e. in "big-endian" order). So, for example,
IntegerToString(1, 4)="00000001", IntegerToString(7658, 3)="001DEA"
StringToInteger(S) is the integer represented by the byte string S with the most significant byte first. ceiling(x) is the smallest integer, n, such that n x. This is also written as x. ** Strictly speaking, this is the length of the shortest byte string that can encode the integer.
1. The message block is the byte string "8002EA". 2. Compute the message representative
3. 5. 7. m = StringToInteger("8002EA") = 8389354 c = 8389354^5 mod 25009997 = 2242555 OB = IntegerToString(2242555, 4) = 002237FB
4. Encrypt with the RSA algorithm 6. Encode the result as a byte string Note that the maximum length of the output block is 4 bytes, because the largest possible integer result is 0x017D9F4C (= n-1), which requires 4 bytes to store in encoded form.
Thanks to "doctorjay" for pointing out that e=3 did not work for the earlier version of this example.
Implementation in C and VB
We show an example implementation of the RSA algorithm in C in our BigDigits library. It's not necessarily the most efficient way, and could be improved in its security, but it shows the maths involved. Look in the BigDigits Test Functions. There is an example in VB6/VBA code at RSA and Diffie-Hellman in Visual Basic. For a professional implementation, see our commercial CryptoSys PKI Toolkit which can be used with Visual Basic, VB6, VBA, VB2005+, C/C++ and C# applications. There are examples using the `raw' RSA functions to carry out RSA Encryption and RSA Signing.
References
[AX931] ANSI X9.31-1998 Digital Signatures using Reversible Public Key Cryptography for the Financial Services Industry (rDSA), Appendix A, American National Standards Institute, 1998. [CMS] RFC 5652. Cryptographic Message Syntax (CMS), R. Housley, September 2009 (obsoletes RFC3852, RFC3369, RFC2630). [CMSRSAKEM] J. Randall, B.Kaliski. Use of the RSA-KEM Key Transport Algorithm in CMS, draft-ietf-smime-cms-rsa-kem-05.txt, September 2007 (now superseded). [COCK73] Clifford Cocks. A Note on 'Non-Secret Encryption', CESG Research Report, 20 November 1973, <link>. [EDIFACT] UN/EDIFACT Finance Group D6 SWG-F. Recommended Practice For Message Flow And Security For EDIFACT Payments , Version 2v03, 1 October 2000, <link>. [FERG03] Niels Ferguson and Bruce Schneier, Practical Cryptography, Wiley, 2003. [KALI93] Burton Kalinski. Some Examples of the PKCS Standards, RSA Laboratories, 1999, <link>. [NIST-80057] NIST Special Publication 800-57, Recommendation for Key Management - Part 1: General (Revised), Elaine Barker et al, National Institute of Standards and Technology, March 2007.
[P1363] IEEE P1363 Standard Specifications for Public Key Cryptography, IEEE, November 1993. [PKCS1] RSA Laboratories. PKCS #1 v2.1: RSA Encryption Standard. June 2002, <link>. [RIVE78] R. Rivest, A. Shamir and L. Adleman. A Method for Obtaining Digital Signatures and Public-Key Cryptosystems. Communications of the ACM, 21 (2), pp. 120-126, February 1978, <link>.
Author
The content of this page is all original work written by David Ireland, who reserves all intellectual rights. You may freely link to this page. You may use parts of the work for fair dealing for the purposes of research or private study as permitted under copyright law, but you may not post any part of this content on another web site without the explicit permission in writing of the author.
Feedback
Feedback or questions: Contact Us. To comment on this page, see below. Please note we are not an oracle for college assignment questions. Your tutors read this page, too! This page last updated 11 May 2012