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.
Related
I am currently trying to figure out a concrete way to perform fixed point division on two 128.128 uint256 numbers. This seems like a fairly straightforward thing, but haven't been able to code a solution up.
For two 64.64 fixed point numbers the following works just fine.
function div64x64 (uint128 x, uint128 y) internal pure returns (uint128) {
unchecked {
require (y != 0);
uint256 answer = (uint256 (x) << 64) / y;
require (answer <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
return uint128 (answer);
}
}
But the same logic does not hold for uint256 128.128 fixed point numbers since you cannot cast x into a larger uint type to left shift x. This is my sad attempt at solving this for 128.128 which doesn't include the correct decimals in the output, but my attempt does include the correct values left of the decimal.
function div128x128 (uint256 x, uint256 y) internal pure returns (uint256) {
unchecked {
require (y != 0);
uint256 xInt = x>>128;
uint256 xDecimal = x<<128;
uint256 yInt = y>>128;
uint256 yDecimal = y<<128;
uint256 hi = ((uint256(xInt) << 64)/yInt)<<64;
uint256 lo = ((uint256(xDecimal)<<64)/yDecimal);
require (hi+lo <= MAX_128x128);
return hi+lo;
}
}
Does anyone know the best way to accomplish this, or even just a conceptual explanation of how to do it would be super appreciated. Thanks in advance!
Okay, so I'll post the solution here for the next guy. The key here is one of the more obvious facts that you can break up a fraction with a common denominator into two additive parts. For example 12.525/9.5= (12/9.5)+(.525/9.5) with this in mind we have a way to break up our numbers into 2 uint256 numbers and just concatenate them with some fancy shifting.
function div128x128 (uint256 x, uint256 y) internal pure returns (uint256) {
unchecked {
//Require denominator != 0
require (y != 0);
// xDec = x & 2**128-1 i.e 128 precision 128 bits of padding on the left
uint256 xDec = x & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
//xInt x *2**-128 i.e. 128 precision 128 bits of padding on the right
uint256 xInt = x >> 128;
//hi = xInt*2**256-1 /y ==> leave a full uint256 of bits to store the integer representation of the fractional decimal with 128.128 precision
uint256 hi = xInt*(MAX_128x128/y);
//xDec*2**256-1 /y ==> leave full uint256 of bits to store the integer representation of fractional decimal with 128.128 precision, right shift 128 bits since output should be the right 128 bits of precision on the output
uint256 lo = (xDec*(MAX_128x128/y))>>128;
/*Example: 12.525/9.5 := 12/9.5 + .525/9.5<-- legal to break up a fraction into additive pieces with common deniminator in the example above just padding to fit 128.128 output in a uint256
*/
require (hi+lo <= MAX_128x128);
return hi+lo;
}
}
This is one solution, that seems to be working so long as the require criterion are met. There are almost undoubtedly optimization improvements to be made. But I have tested this on some real data, and it seems to be accurate to 128.128 precision.
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?
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 5 years ago.
Improve this question
Jasoos (Cryptography Algorithm)
I am working on encrypting and decrypt web application. I have built an algorithm that uses 24-byte key to encrypt/decrypt the message.
Review this algorithm and please suggest anything important and fault in this algorithm that can make it perform better. Your contribution can help us to improve our algorithm.
Code is provided on my GitHub
Algorithm:-
1] 24 digit entered/generated key will be converted into ASCII code of 24 digit code.
public void setKey(char[] arr){
for(int i=0;i<24;i++){
key[i] = (int)arr[i];
}
}
2] Entered String will be changed into a character array.
Every character will be then incremented first with the key’s value and changed into 10-bit binary code.
public void Encryption(String text){
char[] msg = text.toCharArray();
int flag = 0;
int l = msg.length;
for(int i=0;i<l;i++){
int a = (int)msg[i];
// System.out.print(msg[i]+" "+a+"-> ");
if(flag>23)
flag=0;
int b=a+key[flag];
flag++;
//System.out.print(b+" | ");
String z = binary(b);
sb.append(lookUpTool(z));
//Character.toString((char)b);
}
//sb.append(sumBinary);
sb = comp1(sb);
}
3] lookUp(): - It will take a 10-bit string as input and a matrix, and divide that string into two 5 bit binary code.
We will then calculate decimal value of each 5-bit binary code.
Example: 0011101101 -> 00111 = 7 and 01101 = 13
We have a matrix of 32 X 32 dimensions which has unique random values from 0 to 1023 and will not be shared publicly.
For 0011101101 we will look for 7th row and 13th column value.
That value will be changed into 10 bits binary code.
public String lookUp(String bits, int[][] mat){
int mid = Math.round((float) bits.length() / 2);
String part1 = bits.substring(0, mid);
String part2 = bits.substring(mid, bits.length());
int row=binaryValue(part1);
int col=binaryValue(part2);;
//System.out.print("row: "+row);
// System.out.println("|| col: "+col);
int a = mat[row][col];
return binary(a);
}
4] We will perform this steps ten times with ten different private matrices by lookUpTool method.
public String lookUpTool(String s){
String s1 = lookUp(s,matrix1);
String s2 = lookUp(s1,matrix2);
String s3 = lookUp(s2,matrix3);
String s4 = lookUp(s3,matrix4);
String s5 = lookUp(s4,matrix5);
String s6 = lookUp(s5,matrix6);
String s7 = lookUp(s6,matrix7);
String s8 = lookUp(s7,matrix8);
String s9 = lookUp(s8,matrix9);
String s10 = lookUp(s9,matrix10);
return s10;
}
Similarly, we will do this for each character in the text/string and encrypt it.
Example:-
Key: c|H#yLzd3PkRte0H,u16zt8N
Message: abcd ef$
After Encryption: 11001111000001101010000010000101101000001110100000101010111001110000011000001000
Your algorithm is completely worthless by any reasonable standard. The most obvious problem is this:
You just gave us a key, plaintext, and corresponding encoded message. This leaks out numerous entries from your super-secret matrix that you weren't supposed to share publicly. (Each ten-bit chunk of the encrypted message is an entry from that array, and with the key and plaintext, I can figure out which one it is.)
Imagine if an adversary had a collection of messages that were already encrypted by your algorithm and then you posted this challenge. He can now decrypt a significant fraction of those messages, just from what you leaked in this challenge. And if there are obvious missing bits, say he has "trans_ormer", he can work out another entry in your formerly super-secret array.
But please read the links in the comments. Trying to design your own encryption algorithm for actual use and reliance in this way is absolutely foolish. A new algorithm cannot even be considered for actual use before it has been reviewed thoroughly by experts in each type of known cryptanalysis.
Another algorithmic flaw is immediately obvious. An attacker will know that the key repeats every 24 characters. With a long enough message, say in English, the attacker can do a frequency analysis for each set of every 24th character. It's even worse if the attacker knows the message format and that format has an even more unequal frequency distribution.
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.
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...