RSA decryption without Private Exponent - encryption

I want to decrypt a 1024 bit data which was encrypted using RSA-public key encryption.
I have access to
public key modulus,
public key exponent,
prime p,
prime q,
exponent1 (d mod(p-1)),
exponent2 (d mod(q-1)) and
coefficient ( (1/q) mod p )
I dont have access to private key exponent. Is there any way to decrypt the data without the RSA private exponent and all these available apis ?
I m using openssl for RSA operation.
I heard that with chinese reminder therem, we need only p,q,exponent 1, exponent 2 and coefficient for RSA-decryption. But I'm looking for apis in openssl. Is there any useful way in openssl to decrypt without private exponent ?

Just check the openssl source for generating key pairs...
/* create r0, r1, r2, ctx and - of course - d */
/* calculate d */
if (!BN_sub(r1, p, BN_value_one())) goto err; /* p-1 */
if (!BN_sub(r2, q, BN_value_one())) goto err; /* q-1 */
if (!BN_mul(r0, r1, r2, ctx)) goto err; /* (p-1)(q-1) */
if (!BN_mod_inverse(d, e, r0, ctx)) goto err; /* d */
return d;
You may need to generate some temporary variables in above...

Related

Openssl, RSA: why public key is required for private_decrypt?

I use an Openssl library to provide RSA encryption-decryption for my app. And this is what I found:
int RSA_private_decrypt(int flen, unsigned char *from,
unsigned char *to, RSA *rsa, int padding);
RSA_private_decrypt() decrypts the flen bytes at from using the private key rsa and stores the plaintext in to. (From the docs, https://www.openssl.org/docs/man1.1.1/man3/RSA_private_decrypt.html)
To setup RSA structure I use the following method:
int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d);
The n, e and d parameter values can be set by calling RSA_set0_key() and passing the new values for n, e and d as parameters to the function. The values n and e must be non-NULL the first time this function is called on a given RSA object. The value d may be NULL. (From the docs, https://www.openssl.org/docs/man1.1.1/man3/RSA_set0_key.html)
So, when I use the stuff above for decryption as described, everything works fine. I set RSA struct with n, e and d, then pass RSA struct to private_decrypt() with other parameters and get correct result.
But if I do not set e to RSA struct (or set it with random value to avoid not-null constraint), private_decrypt() returns wrong decryption result (all zeroes typically).
So, why does e required for private decryption? As far as RSA algorithm works, it should be enough to have n, d and cipher_text to provide correct result, isn't it?

Is RSACryptoServiceProvider working correctly?

I'm using .NET's implementation of RSA, and two things looked odd to me. I'd like to confirm that it's operating properly.
Background
Using System.Security.Cryptography.RSACryptoServiceProvider with 2048-bit keyword size to perform asymmetric encryption/decrpytion, initially following the example in this question, "AES 256 Encryption: public and private key how can I generate and use it .net".
As a first implementation, this seems to work:
public const int CSPPARAMETERS_FLAG = 1; // Specifies RSA: https://msdn.microsoft.com/en-us/library/ms148034(v=vs.110).aspx
public const bool USE_OAEP_PADDING = false;
public const int KEYWORD_SIZE = 2048;
public static byte[] Encrypt(byte[] publicKey, byte[] dataToEncrypt)
{
var cspParameters = new System.Security.Cryptography.CspParameters(CSPPARAMETERS_FLAG);
byte[] encryptedData = null;
using (var rsaProvider = new System.Security.Cryptography.RSACryptoServiceProvider(cspParameters))
{
try
{
rsaProvider.PersistKeyInCsp = false;
rsaProvider.ImportCspBlob(publicKey);
encryptedData = rsaProvider.Encrypt(dataToEncrypt, USE_OAEP_PADDING);
}
finally
{
rsaProvider.PersistKeyInCsp = false;
rsaProvider.Clear();
}
}
return encryptedData;
}
public static byte[] Decrypt(byte[] privateKey, byte[] dataToDecrypt)
{
var cspParameters = new System.Security.Cryptography.CspParameters(CSPPARAMETERS_FLAG);
byte[] encryptedData = null;
using (var rsaProvider = new System.Security.Cryptography.RSACryptoServiceProvider(cspParameters))
{
try
{
rsaProvider.PersistKeyInCsp = false;
rsaProvider.ImportCspBlob(privateKey);
encryptedData = rsaProvider.Decrypt(dataToDecrypt, USE_OAEP_PADDING);
}
finally
{
rsaProvider.PersistKeyInCsp = false;
rsaProvider.Clear();
}
}
return encryptedData;
}
After looking into these methods a bit more, it seems that the public key that I've been generating as from the example seemed to have a lot of very predictable data at its start, and it was 276-bytes long.
Apparently rsaProvider.ExportCspBlob(bool includePrivateParameters) is a functional alternative to rsaProvider.ExportParameters(bool includePrivateParameters); the main difference is that the blob is already serialized as a byte[] while the other emits the object version, RSAParameters.
Two observations about the methods:
The .Exponent is always 0x010001$=65537$.
The exported blobs contain 17 extra bytes versus the serialized typed versions.
rsaProvider.ExportCspBlob():
Public key is 276 bytes.
Private key is 1172 bytes.
RSAParameters:
Public key is 259 bytes.
.Exponent.Length = 3
.Modulus .Length = 256
Private key is 1155 bytes.
.D .Length = 256
.DP .Length = 128
.DQ .Length = 128
.Exponent.Length = 3
.InverseQ.Length = 128
.Modulus .Length = 256
.P .Length = 128
.Q .Length = 128
The extra 17 bytes appear to be at the header of the binary blob.
Concerns
From this, two concerns:
Is it okay for the exponent to not be random?
If the exponent is defined as a constant, then it'd seem like that's another 3 bytes I could shave off the serialization?
Another question, Should RSA public exponent be only in {3, 5, 17, 257 or 65537} due to security considerations?, seems to suggest that $\left{3, 5, 17, 257, 65537\right}$ are all common values for the exponent, so 0x101$=65537$ seems reasonable if it's true that there's no harm in always using the same constant exponent.
Are the 17 extra bytes an information leak?
Do they represent the option parameters like key length and method?
Is it a good idea to be transmitting option parameter information when I already know that both the sender and receiver are using the same, hard-coded method?
Question
Is RSACryptoServiceProvider's behavior a cause for concern, or are these things normal?
Update 1
In Should RSA public exponent be only in {3, 5, 17, 257 or 65537} due to security considerations?, the accepted answer starts off by noting:
There is no known weakness for any short or long public exponent for RSA, as long as the public exponent is "correct" (i.e. relatively prime to p-1 for all primes p which divide the modulus).
If this is so, then I'd guess that the apparently-constant exponent of 0x010001$=65537$ is sufficient as long as it's relatively prime to $p-1$. So, presumably the .NET implementation of RSA checks for this condition.
But then what does RSACryptoServiceProvider do if that condition isn't satisfied? If it selects a different exponent, then that'd seem to leak information about $p$ whenever the exponent isn't 0x010001. Or, if a different key is selected, then it'd seem like we can just assume that the exponent is always 0x010001 and omit it from the serialization.
Everything reported is normal, and non-alarming.
It is perfectly OK for the public exponent e to be short and non-random. e = 216+1 = 65537 = 0x010001 is common and safe. Some authorities mandate it (or some range including it). Using it (or/and something significantly larger than the bit size of the public modulus) gives some protection against some of the worst RSA paddings.
No, the 17 extra bytes in the public key are unlikely to be an information leak; they more likely are a header part of the data format chosen for an RSA public key by the software you use. My guess is that you are encountering the MS-specific format detailed in this answer (perhaps, within endianness), which also uses precisely 276 bytes for an RSA public key with a 2048-bit public modulus. In that case, you should find that the extra bytes are always the same (thus they demonstrably leak nothing). And there are countless more subtle ways to leak information about the private key, like in the public modulus itself.
Many RSA key generators used in practice, including I guess RSACryptoServiceProvider, first choose e, then somewhat avoid generating primes p such that gcd(e, p-1) ≠ 1. Since e = 65537 is prime, it is enough that ( p % e ) ≠ 1, and this is easily checked, or otherwise insured by the process generating p.

Private key length > public key?

I'm working on rsa private and public key / encryption / decryption / etc using openssl module. But a question is still unanswered : why private key are often (are always, i don't know) longer than public key ?
Is there several answer to this ?
This is my public and private key generated.
why private key are often (are always, i don't know) longer than public key ?
The answer is detailed in PKCS 1 (and friends like RFC 2437).
The public key is the pair {e, n}, where e is the public exponent and n is the modulus.
One of the private key representations is the triplet {e, d, n}, where e is the public exponent, d is the private exponent and n is the modulus.
The other private key representations the n-tuple{e, d, n, p, q, dp, dq, qi}, where e is the public exponent; d is the private exponent; n is the modulus; and p and q are the factors of n.
And the remaining are for the Chinese Remainder theorem, which allows a speedup in signatures (I believe). dp is p's exponent, a positive integer such that e(dP) ≅ 1 (mod(p-1)); dq is q's exponent, a positive integer such that e(dq) ≅ 1 (mod(q-1)); and qi is CRT coefficient, a positive integer less than p such that q(qInv) ≅ 1 (mod p).
The RSA private key includes the values that are in the RSA public key, and some more values that are private. Futhermore, the values themselves are larger.
The public key contains the modulus and the public exponent e which is short (mostly 3 or 65537). On the other hand the private key contains the private exponent d ≡ e−1 (mod φ(n)). Depending on φ(n), d can be vastly larger than e.
There are other public key algorithms where this is different. Some algorithms based on elliptic curves have a single big integer as the private key (and group description) and the public key has a curve point (and group description) which is larger than the big integer.

How can I best check these Elliptic Curve parameters are valid?

(Just abit of context:) I'm a novice to Cryptography, but for a school project I wanted to create a proof of concept 64-bit ECC curve. (Yes I do know 64-bit keys are not very secure!) However afaik there is no SEC standard parameters for 64-bit, only 160-512bit.
So I had to go about generating my own parameters, which is the bit i'm (quite) unsure on. I followed a quick guide, and came out with these parameters for my curve:
p = 10997031918897188677
a = 3628449283386729367
b = 4889270915382004880
x = 3124469192170877657
y = 4370601445727723733
n = 10997031916045924769 (order)
h = 1 (co-factor)
Could someone give me some advice as to if this curve will generate valid private/public key pairs? How could I check this?
Any help (/confirmation) would be greatly appreicated, thanks!
You can use OpenSSL's EC_GROUP_check() function to make sure it's a valid group. In the following program I did two things:
Generate an EC_GROUP with the provided parameters, and check if it's valid
Generate an EC_KEY using the generated EC_group, and check if it's valid
Note that it is the EC group you want to check if it can be used to generate valid EC keys, not EC curve.
Please read the comments for details:)
// gcc 22270485.c -lcrypto -o 22270485
#include <openssl/ec.h>
#include <stdio.h>
int main(){
BN_CTX *ctx = NULL;
BIGNUM *p, *a, *b, *x, *y, *order;
EC_GROUP *group;
EC_POINT *G;
int ok = 1;
ctx = BN_CTX_new();
p = BN_new();
a = BN_new();
b = BN_new();
x = BN_new();
y = BN_new();
order = BN_new();
/* Set EC_GROUP */
group = EC_GROUP_new(EC_GFp_mont_method());
BN_dec2bn(&p, "10997031918897188677");
BN_dec2bn(&a, "3628449283386729367");
BN_dec2bn(&b, "4889270915382004880");
EC_GROUP_set_curve_GFp(group, p, a, b, ctx);
/* Set generator G=(x,y) and its cofactor */
G = EC_POINT_new(group);
BN_dec2bn(&x, "3124469192170877657");
BN_dec2bn(&y, "4370601445727723733");
BN_dec2bn(&order, "10997031916045924769");
EC_POINT_set_affine_coordinates_GFp(group,G,x,y,ctx);
EC_GROUP_set_generator(group,G,order,BN_value_one());
/* Checks whether the parameter in the EC_GROUP define a valid ec group */
if(!EC_GROUP_check(group,ctx)) {
fprintf(stdout, "EC_GROUP_check() failed\n");
ok = 0;
}
if (ok) {
fprintf(stdout, "It is a valid EC group\n");
}
/* Generate a private/public key pair with above EC_GROUP */
if (ok) {
BIGNUM *private_key, *pub_x, *pub_y;
EC_POINT *public_key;
EC_KEY *eckey;
pub_x = BN_new(); pub_y = BN_new();
eckey = EC_KEY_new();
/* create key on group */
EC_KEY_set_group(eckey,group);
EC_KEY_generate_key(eckey);
/* Verifies that a private and/or public key is valid */
if (!EC_KEY_check_key(eckey)) {
fprintf(stdout, "EC_KEY_check_key() failed\n");
ok = 0;
}
if (ok) {
fprintf(stdout, "It is a valid EC key, where\n");
private_key = EC_KEY_get0_private_key(eckey);
fprintf(stdout, "\tprivate key = %s",BN_bn2dec(private_key));
public_key = EC_KEY_get0_public_key(eckey);
EC_POINT_get_affine_coordinates_GFp(group,public_key,pub_x,pub_y,ctx);
fprintf(stdout, "\n\tpublic key = ( %s , %s )\n",
BN_bn2dec(pub_x),BN_bn2dec(pub_y));
}
BN_free(pub_x); BN_free(pub_y);
EC_KEY_free(eckey);
}
if (ctx)
BN_CTX_free(ctx);
BN_free(p); BN_free(a); BN_free(b);
EC_GROUP_free(group);
EC_POINT_free(G);
BN_free(x); BN_free(y); BN_free(order);
return 0;
}
Compile and run with this command:
$ gcc 22270485.c -lcrypto -o 22270485
$ ./22270485
The stdout should print
It is a valid EC group
It is a valid EC key, where
private key = 1524190197747279622
public key = ( 3228020167903858345 , 9344375093791763077 )
The private/public key pair will change every time, since EC_KEY_generate_key(eckey) randomly chooses a private key and compute the corresponding public key for every run.

One-to-one integer mapping function

We are using MySQL and developing an application where we'd like the ID sequence not to be publicly visible... the IDs are hardly top secret and there is no significant issue if someone indeed was able to decode them.
So, a hash is of course the obvious solution, we are currently using MD5... 32bit integers go in, and we trim the MD5 to 64bits and then store that. However, we have no idea how likely collisions are when you trim like this (especially since all numbers come from autoincrement or the current time). We currently check for collisions, but since we may be inserting 100.000 rows at once the performance is terrible (can't bulk insert).
But in the end, we really don't need the security offered by the hashes and they consume unnecessary space and also require an additional index... so, is there any simple and good enough function/algorithm out there that guarantees one-to-one mapping for any number without obvious visual patterns for sequential numbers?
EDIT: I'm using PHP which does not support integer arithmetic by default, but after looking around I found that it could be cheaply replicated with bitwise operators. Code for 32bit integer multiplication can be found here: http://pastebin.com/np28xhQF
You could simply XOR with 0xDEADBEEF, if that's good enough.
Alternatively multiply by an odd number mod 2^32. For the inverse mapping just multiply by the multiplicative inverse
Example: n = 2345678901; multiplicative inverse (mod 2^32): 2313902621
For the mapping just multiply by 2345678901 (mod 2^32):
1 --> 2345678901
2 --> 396390506
For the inverse mapping, multiply by 2313902621.
If you want to ensure a 1:1 mapping then use an encryption (i.e. a permutation), not a hash. Encryption has to be 1:1 because it can be decrypted.
If you want 32 bit numbers then use Hasty Pudding Cypher or just write a simple four round Feistel cypher.
Here's one I prepared earlier:
import java.util.Random;
/**
* IntegerPerm is a reversible keyed permutation of the integers.
* This class is not cryptographically secure as the F function
* is too simple and there are not enough rounds.
*
* #author Martin Ross
*/
public final class IntegerPerm {
//////////////////
// Private Data //
//////////////////
/** Non-zero default key, from www.random.org */
private final static int DEFAULT_KEY = 0x6CFB18E2;
private final static int LOW_16_MASK = 0xFFFF;
private final static int HALF_SHIFT = 16;
private final static int NUM_ROUNDS = 4;
/** Permutation key */
private int mKey;
/** Round key schedule */
private int[] mRoundKeys = new int[NUM_ROUNDS];
//////////////////
// Constructors //
//////////////////
public IntegerPerm() { this(DEFAULT_KEY); }
public IntegerPerm(int key) { setKey(key); }
////////////////////
// Public Methods //
////////////////////
/** Sets a new value for the key and key schedule. */
public void setKey(int newKey) {
assert (NUM_ROUNDS == 4) : "NUM_ROUNDS is not 4";
mKey = newKey;
mRoundKeys[0] = mKey & LOW_16_MASK;
mRoundKeys[1] = ~(mKey & LOW_16_MASK);
mRoundKeys[2] = mKey >>> HALF_SHIFT;
mRoundKeys[3] = ~(mKey >>> HALF_SHIFT);
} // end setKey()
/** Returns the current value of the key. */
public int getKey() { return mKey; }
/**
* Calculates the enciphered (i.e. permuted) value of the given integer
* under the current key.
*
* #param plain the integer to encipher.
*
* #return the enciphered (permuted) value.
*/
public int encipher(int plain) {
// 1 Split into two halves.
int rhs = plain & LOW_16_MASK;
int lhs = plain >>> HALF_SHIFT;
// 2 Do NUM_ROUNDS simple Feistel rounds.
for (int i = 0; i < NUM_ROUNDS; ++i) {
if (i > 0) {
// Swap lhs <-> rhs
final int temp = lhs;
lhs = rhs;
rhs = temp;
} // end if
// Apply Feistel round function F().
rhs ^= F(lhs, i);
} // end for
// 3 Recombine the two halves and return.
return (lhs << HALF_SHIFT) + (rhs & LOW_16_MASK);
} // end encipher()
/**
* Calculates the deciphered (i.e. inverse permuted) value of the given
* integer under the current key.
*
* #param cypher the integer to decipher.
*
* #return the deciphered (inverse permuted) value.
*/
public int decipher(int cypher) {
// 1 Split into two halves.
int rhs = cypher & LOW_16_MASK;
int lhs = cypher >>> HALF_SHIFT;
// 2 Do NUM_ROUNDS simple Feistel rounds.
for (int i = 0; i < NUM_ROUNDS; ++i) {
if (i > 0) {
// Swap lhs <-> rhs
final int temp = lhs;
lhs = rhs;
rhs = temp;
} // end if
// Apply Feistel round function F().
rhs ^= F(lhs, NUM_ROUNDS - 1 - i);
} // end for
// 4 Recombine the two halves and return.
return (lhs << HALF_SHIFT) + (rhs & LOW_16_MASK);
} // end decipher()
/////////////////////
// Private Methods //
/////////////////////
// The F function for the Feistel rounds.
private int F(int num, int round) {
// XOR with round key.
num ^= mRoundKeys[round];
// Square, then XOR the high and low parts.
num *= num;
return (num >>> HALF_SHIFT) ^ (num & LOW_16_MASK);
} // end F()
} // end class IntegerPerm
Do what Henrik said in his second suggestion. But since these values seem to be used by people (else you wouldn't want to randomize them). Take one additional step. Multiply the sequential number by a large prime and reduce mod N where N is a power of 2. But choose N to be 2 bits smaller than you can store. Next, multiply the result by 11 and use that. So we have:
Hash = ((count * large_prime) % 536870912) * 11
The multiplication by 11 protects against most data entry errors - if any digit is typed wrong, the result will not be a multiple of 11. If any 2 digits are transposed, the result will not be a multiple of 11. So as a preliminary check of any value entered, you check if it's divisible by 11 before even looking in the database.
You can use mod operation for big prime number.
your number * big prime number 1 / big prime number 2.
Prime number 1 should be bigger than second. Seconds should be close to 2^32 but less than it. Than it will be hard to substitute.
Prime 1 and Prime 2 should be constants.
For our application, we use bit shuffle to generate the ID. It is very easy to reverse back to the original ID.
func (m Meeting) MeetingCode() uint {
hashed := (m.ID + 10000000) & 0x00FFFFFF
chunks := [24]uint{}
for i := 0; i < 24; i++ {
chunks[i] = hashed >> i & 0x1
}
shuffle := [24]uint{14, 1, 15, 21, 0, 6, 5, 10, 4, 3, 20, 22, 2, 23, 8, 13, 19, 9, 18, 12, 7, 11, 16, 17}
result := uint(0)
for i := 0; i < 24; i++ {
result = result | (chunks[shuffle[i]] << i)
}
return result
}
There is an exceedingly simple solution that none have posted, even though an answer has been selected I highly advise any visiting this question to consider the nature of binary representations, and the application of modulos arithmetic.
Given an finite range of integers, all the values can be permuted in any order through a simple addition over their index while bound by the range of the index through a modulos. You could even leverage simple integer overflow such that using the modulos operator is not even necessary.
Essentially, you'd have a static variable in memory, where a function when called increments the static variable by some constant, enforces the boundaries, and then returns the value. This output could be an index over a collection of desired outputs, or the desired output itself
The constant of the increment that defines the mapping may be several times the size in memory of the value being returned, but given any mapping there exists some finite constant that will achieve the mapping through a trivial modulos arithmetic.

Resources