Trying to generate an RSA Public Key given an APIs modulus and exponent. I'm using OpenSSL on iOS 4.2.
Generating the public key manually is an option (see below) however i'm not sure how to include the exponent logic in the modulus
-----BEGIN PUBLIC KEY-----
Modulus from API
-----END PUBLIC KEY-----
Based on #James comments, I am able to write public pem but getting blank private key. Here is my code:
char szModulus = "1162" ;
char *szExp = "827655" ;
RSA* rsa = RSA_new();
int ret = BN_hex2bn(&rsa->n,szModulus) ;
ret = BN_hex2bn(&rsa->d,szExp) ;
FILE *fp = fopen("/Users/ysi/Desktop/privateKey.pem", "wb");
PEM_write_RSAPrivateKey(fp, rsa, NULL, NULL, 0, 0, NULL);
To do this make sure you have the OpenSSL library linked (instructions here http://code.google.com/p/ios-static-libraries/)
Once linked you'll have access to several BIGNUM converters. I turned the modulus into hex using the BN_hex2bn method saving the hex string into 'exponent'
Then create the BIGNUM struct and encrypt using RSA_public_encrypt
RSA *rsa = NULL;
rsa->n = BN_new();
BN_copy(rsa->n,modulus);
rsa->e = BN_new();
BN_copy(rsa->e,exponent);
rsa->iqmp=NULL;
rsa->d=NULL;
rsa->p=NULL;
rsa->q=NULL;
Good Luck!
Related
I am planning to generate following pin-sha256 :
Public-Key-Pins:
pin-sha256="cUPcTAZWKaASuYWhhneDttWpY3oBAkE3h2+soZS7sWs=";
pin-sha256="M8HztCzM3elUxkcjR2S5P4hhyBNf6lHkmjAHKhpGPWE=";
max-age=5184000; includeSubDomains;
report-uri="https://www.example.org/hpkp-report"
So that i can keep in IIS for security reasons as below:
<system.webServer>
...
<httpProtocol>
<customHeaders>
<add name="Public-Key-Pins" value="pin-sha256="base64+primary=="; pin-sha256="base64+backup=="; max-age=5184000; includeSubDomains" />
</customHeaders>
</httpProtocol>
...
</system.webServ
But my server lacks open ssl and take long time to install because of process issues.
Could you please let me know is there any alternative without these openssl that i can generate pins?
See this link for more details
These are the pin generation commands, i need to do this without openssl , is it possible?
openssl rsa -in my-rsa-key-file.key -outform der -pubout | openssl dgst -sha256 -binary | openssl enc -base64
Here is an example of the openssl command chain above converted into openssl API calls that output the base64 result to the screen.
The main calls are
PEM_read_bio_PrivateKey to read in the private key in PEM format.
i2d_RSA_PUBKEY_bio to convert the RSA public key into DER format
EVP_Digest to create the SHA256 digest (hidden behind the BIO_f_md BIO usage)
BIO_f_base64 BIO usage to convert the digest into base64 format
There are lots of ways to do the same job using variations of the above OPENSSL API's depending on your situation.
Below is a C++ usage of the OpenSSL C API. You can easily strip the C++ bits if required.
template<typename T, typename D>
std::unique_ptr<T, D> make_handle(T* handle, D deleter)
{
return std::unique_ptr<T, D>{handle, deleter};
}
bool load_rsa_private_key_and_base64_sha256_hash_public_key()
{
// load rsa private key in PEM format
auto bio = make_handle(BIO_new_file("privatekey.pem", "rb"), BIO_free);
if(!bio) return false;
auto const key = make_handle(PEM_read_bio_PrivateKey(bio.get(), nullptr, nullptr, (void*)("password")), EVP_PKEY_free);
bio.reset();
if(!key) return false;
// extract private key from loaded certificate
auto const rsa = EVP_PKEY_get0_RSA(key.get());
if (!rsa) return false;
// setup sha256 bio chain
auto const bmd = make_handle(BIO_new(BIO_f_md()), BIO_free);
if(!bmd) return false;
if (!BIO_set_md(bmd.get(), EVP_sha256())) return false;
auto const null_bio = make_handle(BIO_new(BIO_s_null()), BIO_free);
auto in = BIO_push(bmd.get(), null_bio.get());
// write RSA Public Key into DER format to the SHA256 digest BIO chain
i2d_RSA_PUBKEY_bio(in, rsa);
// extract the SHA256 digest
auto mdtmp = BIO_find_type(in, BIO_TYPE_MD);
if (!mdtmp) return false;
std::array<char, EVP_MAX_MD_SIZE> buffer;
auto const length = BIO_gets(mdtmp, buffer.data(), buffer.size());
if(length <= 0) return false;
// convert the digest to base64 and output to the stdio
auto const b64 = make_handle(BIO_new(BIO_f_base64()), BIO_free);
auto const bio_out = BIO_new_fp(stdout, BIO_NOCLOSE);
auto out = BIO_push(b64.get(), bio_out);
BIO_write(out, buffer.data(), length);
BIO_flush(out);
return true;
}
I working on little ECC crypto problem.
The goal is to write a program in C or bash, which will take as input a hash composed of 128 characters in hexadecimal
(Example: 8A9A35145C4EA5260DF9972C804FE2D3F9F3D7A2AC01A6BEB21C82BB30957B3952273AC9166B90C1207347A925780F84A1D2359E7AA05201C674D2B9746FCA07)
and which will generate from the input hash a private key and a public key of type Elliptic Curve and display the key pair generated.
Can someone clarify for me the problem. I can't understand why we need a hash(or any string) to generate a pair key, as I found In many online solution like this one ther's no need to give a hash. Maybe is it a parphase ? Maybe It's the curve key or somthing similar.
I think all we need is to do something like this for the private key:
openssl ecparam -genkey -noout -out myprivatekey.pem
and for the public key generation:
openssl -ec -in myprivatekey.pem -pubout -out mypublickey.pem
The question is : why we need an input a hash composed of 128 to generate our pair keys? Is it a passphrase for security reason? how made the trick with openssl ?
You could use a hash if you've got some kind of input binary value which you need to convert to a key.
You can use a hash as input for a private key. To convert it you should first convert it to a number and then perform a calculation modulo n on it, where n is the order of the ECC domain parameters. The resulting value can be called s Then you can calculate the public key out of it by performing s * G, i.e. point multiplication with the base point.
OpenSSL is not a low level crypto library, so you'd have to program it, possibly using the OpenSSL API and the BN (big number) library that comes with it. It is not that tricky, but if you're still talking about 128 characters instead of 64 bytes then you may have a lot of learning to do.
In fact this is my own code, you can improve it and edit the solution bellow:
// gcc -Wall ecdsapubkey.c -o ecdsapubkey -lcrypto
#include <stdio.h>
#include <stdlib.h>
#include <openssl/ec.h>
#include <openssl/obj_mac.h>
#include <openssl/bn.h>
int main()
{
EC_KEY *eckey = NULL;
EC_POINT *pub_key = NULL;
const EC_GROUP *group = NULL;
BIGNUM *start;
BIGNUM *res;
BN_CTX *ctx;
start = BN_new();
ctx = BN_CTX_new(); // ctx is an optional buffer to save time from allocating and deallocating memory whenever required
res = start;
BN_hex2bn(&res,"8A9A35145C4EA5260DF9972C804FE2D3F9F3D7A2AC01A6BEB21C82BB30957B3952273AC9166B90C1207347A925780F84A1D2359E7AA05201C674D2B9746FCA07");
eckey = EC_KEY_new_by_curve_name(NID_secp256k1);
group = EC_KEY_get0_group(eckey);
pub_key = EC_POINT_new(group);
printf("private key : "); BN_print_fp(stdout, res); printf("\n");
EC_KEY_set_private_key(eckey, res);
/* pub_key is a new uninitialized `EC_POINT*`. priv_key res is a `BIGNUM*`. */
if (!EC_POINT_mul(group, pub_key, res, NULL, NULL, ctx))
printf("Error at EC_POINT_mul.\n");
EC_KEY_set_public_key(eckey, pub_key);
char *cc = EC_POINT_point2hex(group, pub_key, 4, ctx);
char *c=cc;
int i;
printf("public key : ");
for (i=0; i<130; i++) // 1 byte 0x42, 32 bytes for X coordinate, 32 bytes for Y coordinate
{
printf("%c", *c++);
}
printf("\n");
BN_CTX_free(ctx);
free(cc);
return 0;
}
How can I implement the effect of following command in Objective-C?
openssl rsa -in mykey.pem -pubout > mykey.pub
I'm able to generate a private key in pem format.
Here is the code I use to read the private key into a openssl RSA object.
BIO* bpPrivate = nil;
NSString *filePath = .....
const char *path = [filePath UTF8String];
bpPrivate = BIO_new_file(path, "r");
_rsa = PEM_read_bio_RSAPrivateKey(bpPrivate, NULL, 0, NULL);
I want to extract the public key from the private key.
In memory, there is no notion of ASN.1, DER, PEM or other encodings. A RSA key uses the same structure for both the public and private key. For a public key, some fields are not used. If you are interested in the fields, then visit PKCS #1 or RFC 3447.
So, given an RSA*, all you need to do is call PEM_write_bio_RSAPublicKey (even with a private key). You can also use PEM_write_RSAPublicKey (even with a private key). See pem(3) for all the read and write functions.
You can also accomplish it the long way by way of RSAPublicKey_dup. It will take a priavte key (i.e., a RSA*) and return a public key (i.e., a RSA*). But its kind of an unnecessary step for the most part. It might be useful to keep the key in memory, if you have that requirement.
RSA* privKey = NULL;
RSA* pubKey = NULL;
BIGNUM* exp = NULL;
privKey = RSA_new();
ASSERT(privKey != NULL);
exp = BN_new();
ASSERT(exp != NULL);
rc = BN_set_word(exp, RSA_F4);
ASSERT(rc == 1);
rc = RSA_generate_key_ex(privKey, 1024, exp, NULL);
ASSERT(rc == 1);
pubKey = RSAPublicKey_dup(privKey);
ASSERT(pubKey != NULL);
RSA_print_fp(stdout, pubKey, 0);
if(pubKey) {
RSA_free(pubKey);
}
if(privKey) {
RSA_free(privKey);
}
if(exp) {
BN_free(exp);
}
The RSA_print_fp results in:
$ ./t.exe
Public-Key: (1024 bit)
Modulus:
00:c3:30:67:d9:11:59:9b:85:7a:1a:95:fa:fd:c0:
dd:cd:21:d6:41:6b:16:70:c2:57:9a:f2:d2:bd:3b:
c0:02:7b:6a:ab:7f:13:a7:53:2f:31:10:08:3a:62:
28:40:5f:82:19:23:f6:0f:78:f5:e3:e4:19:a1:b4:
73:65:35:10:db:17:28:41:42:ba:df:8c:18:3b:d8:
62:52:65:61:0e:cd:60:28:c9:75:a8:5b:46:a4:89:
db:78:89:49:87:5d:7f:ce:d0:44:c4:fd:4a:74:66:
d4:46:21:c1:89:97:28:de:43:e9:94:50:f1:36:85:
a7:ef:6c:6d:6f:5d:78:00:67
Exponent: 65537 (0x10001)
You can add a call to PEM_write_RSAPublicKey:
FILE* file = fopen("rsa-pub.pem", "w");
ASSERT(file != NULL);
rc = PEM_write_RSAPublicKey(file, pubKey);
Then:
$ ./t.exe
$ cat rsa-pub.pem
-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBAMb2jIVcTttHRqG9szv3CFZ742l7LxnVoM6oOfQXNOwabh+GB4Srf4IA
XRcGan7cj1DShnoPw9fp3IeuAUerk3xz8yPXCw09dLwrFcsmItLVnSLoRtpHnxN5
30Wd5vKpvKTLIQnurGo05s911ukFJeGo2y2OjSnTiQcJLUdt497tAgMBAAE=
-----END RSA PUBLIC KEY-----
I've generated a key with openssl by using the following command
openssl genrsa 1024
I've got the following result
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQC2Lh4HLcCR76Wv3oXl6sZ7pv8l9b/66H+I6Bb86tz8RhWCmTCG
xPVgtZ+w9WutU/rqBHHZOpotX4QDksRD8dRFh6a3HwkIFQdTcDoiD39yNP8F02Gd
dAl8p/URC5jNCLMSfUK38wMocmoI1I5vqdMNrzUnOup18rl4089Z+faMKQIDAQAB
AoGBAJrL4z5iWiengxqV8yETBeU8WcJft+n0dapXzHDNAUo8Izr+AIYEBp1Ot4se
f4igu6zuae80JJ45c2u14p/5dWzN9/URmhTP8xLGjGCjltOJLLyhBPP+ZsLjqu6l
57MNV6jDqDLdRC66w4NMRCN3FACxcldIC5L6B9OA7UvO1ugBAkEA8s1o6BvufTeD
ktyOMfW0ZeLGk/6EXp8nf7BIzYhAAPtSt8DegnfYFx2XDgKnYSB15dTDIDMe/KaA
GcuUb/ZjiQJBAMATb1fFdl7PGccVPgeTaupJayHPySc9PSsACV6VIAnpcU/3NZzd
MkdIL/JsOsD+1M9uQJqvRZO4qQdjcR5Om6ECQEJGgYlB/pJdcePHomTOvcRF55CE
G9u8M8rt8qFvvJDICWcxFUulrO16XT4syUWA1825it2iNqYeSL9By63YIokCQBnm
RPw71xM/r8UleyDAYwlGbxi3EPOmkUnsDldfmltby/ixZ9xIA1CTTkvNBjsh4YY6
4qE5AxPBMaGaahVhGiECQHyQvXUNE2IUco+ZwmmLnb2ey1s5tBg7i0lEZG47G7GV
o+yKdJHpToJD8eRJA/2D+pMhQIZm8X/XDIoi1AQ/TRY=
-----END RSA PRIVATE KEY-----
By using http://lapo.it/asn1js/ I've decompiled above pem and found out that
p = 12716592588957205057720227362856602359162165918588008158928004904780617816265357754968000322907349867949577092305558696339499022301055839537975977118688137
q = 10059832080410675679274931119486090017360564066559599189867309386706046720813347145402059918876964980032136051476889631968099168811652389989474036177869729
But in the mean time the modulus
n = 127931248913253271289716500205639992466284651287857358177145251825312810367993147780821624164062592337708505486275588028025122128928225266601591073331803580493341719724935049328478344297205955905466581637169109448199715137939448946445804542355907923908845024638480376219852266194827768486624319018352514599977
When it should equal:
N = 127926786079904340486324750015310657558743663036816604629670248604945247855865212421871439992814824964459404054462886419168595224468110358113599485755243718536935880977456835036272916419632947427885989469252242704342884476060911074859116149906854382812141105735147419775039435625802885168567201322191763704873
Why the hell N is not equal to p * q ?
EDIT:
Here is bunch of keys generated by my openssl, I'm using Mac OS X Mavericks, the first key has correct N, the second one incorrect, I haven't checked the others, but anyway this issue seems to be reproducing, I'm using the following openssl version "OpenSSL 0.9.8y 5 Feb 2013":
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDb4ZTDCASpFV+89RzD8MYR/xASV/piyXB3+qVq+PueDqq+45EL
Xt5UE2jXanfOh3uE3G3Fi76rm08XUC0CvFB7DxFJAMvchr5LbE9x2EMDmfpuZPOI
bDI+r+XZ+KJF++h296TOnncgnXILoD1gihkld7MS9g49TwsBPOtsMJzDRQIDAQAB
AoGBAMpGFfTormjhacZJcqHqIDwz+RP27TbtetJUuNHUpJw9f+PFMwxTxJFxnZP1
tKtAxWdu5GjDaq8xW6vlrNKEbD9jg2WU/myYffNeHxNVjivzypeQzBSmcE5LKFpM
objHkvXbBkkyX8Oh6ZF/3+NOhxOVZMH7CaZ90a+xPf7ENXJBAkEA+Zx/rwrx81+D
s79thCAUU4EnMVROGFPr/V7mt9AFXjAXHRuvg49Aon23bt48jdroakV5vk0ltKO8
Z5xnRWlGNQJBAOGCSOL+zFJd6zTM+CkbgGtml+DIunr7Avfu2mZyaMv4mLo+GTRN
ctZEKhknYfydewhORLKg51WdLThoe9VG6tECQCUyIvzMnr1rkE6qygEUXrMK3fJF
49VQPCxnhe4CO6qLdAZMZ90s7a7JGRqWV2O0KUoczEWFbYb7l0nBTspTI7kCQGmT
L0BmfY3KPoWXuE62e2bMvyoTj4pn3bnpbwIrafikSAxZaj9cSvkZLIReNbeomqMG
0Y63WdZxIWyZLfBppSECQQCEIkbINrQPJHoLtD57AbptUeyaE5lQBurzXMVf84FA
OJjd5OKmEX+LYbLguzOjvkcysNEZBRphz4L07shvscBC
-----END RSA PRIVATE KEY-----
-----BEGIN RSA PRIVATE KEY-----
MIICXgIBAAKBgQDTzIPHUoq9I+Fmdc8kdpuu6BSzLAmLsXv1FKXdHSYSmqI3HRTs
ZcYDSM1Vp/Svf6jdt2uNuNt0UaXzFowT9fi+sIFE2Zlpl8nEM66YZYHJfHQXy6GR
h2ybiNcDEigasc1wBvbkdSR9RNLUnLzX6YNY+197CY6vgW0R0pzuRRR/JQIDAQAB
AoGBAKAeu3mTM4QufhdB9WoxqR0gI5YZMtZDRd1Q0NxLTx89fGmCOPFHN93/ygx5
v4h2UKneIxevq2lS2MzgPOJSUMwn14/19iujT2+jC6vHKpwcjkGrnLXdsdjowrHJ
X3tnbZC4pS/2UU8r/QKzwX957+Idn4Mt2v2sDzQj5ZoPRtfBAkEA/GLl6BXQQp/4
ymsytyM6gleLdaIklCESUc6yZpY48HJqqg3lJwy/3bgb9fYlok/DPbyiEK/p+cXL
lXycbdA6HQJBANbU2MAwpBprkyliEvb+WAvyIGuf3xCVJq3CicuWfJphtMdUEsQm
cpGbQp/0bXUuFkks/xOFMKfBkAbn7Z5tCqkCQQCffcP56ScFo2AuUpXnA50q1zXr
LX7eGRQhnHRCvfXXhQaA1m0UQ0tQStNomJdpvewMrJLh5rj+PY+MtQWJo8fFAkBm
H5RR+E1qSc0RFRAS3eGY/CaxQrRVO7HBVAMRBp6A/QVk4/Bv0h8QXJAVXapS0+/A
JWW0L9JrTLZcsg/hCdDRAkEAmHZNomd/wptVccGwXtgXIL5ElQWLL/3WEggCqOIp
c+v9IRpKND9qn1zwu3tnBrrUbmC2M8CEOnuHP+lnumc2YQ==
-----END RSA PRIVATE KEY-----
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQCWVkOkNXkWd2QoWudAD8rrzioby2g8k1pruaclCMo2mSns++TG
S3lWgLqS2mPynNONVbqoOedLKKnGY9HYzLCOCuoq5loOYCtIcVyBVGhx4eQrZgmU
AwRqQChztrj09+omveQQF2+QW9DJZrYSsKB836iTt5oAEA3ER6fwcV3fLQIDAQAB
AoGAQKNife4H3CMFS1yaZS7lHrIL5Nt2O+VXUU4HkaLP3t3H6v77BE9bIlhC3/VK
V/wZ8YDUupP64JPhO02b4k1P83oG5SAFTb0zZwmHI1+wVnNomq0DoRPw2710a2P4
Ya09nLbuRlm6SzsAkuwmyv+fPDas8b/m15kWSP/HTKMbAPkCQQDEUaTQUg/8sPH+
jDraHpjGtVRqjkysAZhNgMH+NGWLbk3nujZj4oMfid+4Xg4/Sr5EADqr0HrSlMnV
hhlwBCxjAkEAxAodCSmu9khiuRzMzXAc/gvqdtq+fF6Zx+rTUF5HYeD7l1u3SXes
whDku23Pp41+A4axWHXHTsDlKv49m9YzLwJBAJWIEl9SgjbYmBpouVL2RyvjZf8b
kC7bsCQoVJrJUicXx2MfpNoD6BgXrj4B9hwjVDT7b7T6wPKwveNTlwCJTT0CQGNJ
W/tQCTTi5F0soO1LYuOn1U/s6ZzDrM77t5p0pWKFN+copGOpIO4I8E+dBhauKqxO
g3Nx80eHmolzynAqxDECQEmyZq1mFEpB6buwNhRmj/kyOGmA88IbovZhBT+Un/6o
heaaMVl7Hst7nhihxQ081c3mFuwnH/mjixKKkpVens8=
-----END RSA PRIVATE KEY-----
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQCm7mMUqExF5Nq2qzQ8gLVfq5AqKQlKm47Df4H/XqH9msGNCoIx
tnH4Tbe38tzA9TDRxxYQ6oCmTRUlKqstxb0j8NK7KV63vrxhLUlCIinMk9qcTL/T
tLm7/rBSZ7M6OjupzjjQ8Idu7Jd7HVITvFDYbDtd0uDh7Hd1GCrqrHnAoQIDAQAB
AoGABjMgVuoROx9OyC3/mKenFNCIYCh6Ad1ZJgWcTGG1Xnfa7GQRhcsi3Hf2dMx+
SmRQ1dmxBhvPf12phWHaTa7kYVvyXWVbp4OYPsU24/WuVfXysmA1FhO4OJMoTEqQ
FtNGmC05vhwNge+zuyiyj+4Rvhe4CRWeAlWQT9ucOZStoAECQQDdM7qny+KGMysi
sUttOal551Ow1GsM6vo990tZP5jKD/lYkLhi4GBtib66pdqyizUhQoS5stFgvUk9
ztc8cUKBAkEAwTEOaypn6oUtDZMAiIW8a0m0bNtkXRnSb6UaG6n3VEEz8wkjg2Kx
ZJWIl+vk1JZKlJUOWrH2FhJexEOMt20uIQJBAJWVS5341ABoTb0yI42DNsYG1qN3
ocSkigCpYDzEMvBBiR6JDwdeMBci1OWnDpM6a/1H3DUvZUOD/Slc3FQ1SwECQHfO
93UoWEeNjbIkXylLXt1eWSFFMcm3ENUiG73aO0MqKJBpM3fwhbiuL4afyUq5Zckd
Y0iFoupvPAwVJDhA4mECQQCG/UmJG+N0Stt3nn16QzJwwGu7djFXFgSYn8LGIrRM
E3pfC6OMcJ3exAR5t78Bth1VLbST2S2AWNaT0d0fsSA/
-----END RSA PRIVATE KEY-----
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQC0n8+Te4265j0QqqTyV0QnGbU/v9YWqTWAbfvNwXE5nZuJoLuP
yzL4wjcZknBjQCBLsO64a9rxZx5fmL3R+kHjcF6S8OBB9NEXRk70D+vFgHjexGR9
mOk/SXRjfFfaC/pMiSmbuJMFvGCEcii/9tpm03xYWMvpkjn1UEX69BE+TwIDAQAB
AoGADkEebJEvmjRZVVtiMQ3Z/wv0VdeZ2af45O3JFW/Ss61QfQgGRU7P8vnAx2/b
FroU0mRgMoWwfaSZrQms0UlisaI5lEQu7LbhQZqwV+Bz9h784RAHyHLoTTcHRJ/+
TvRT/naCcwzXzHoSQrXmruIbMh6w0KeqVveA9ZI7RMaAZkECQQDpv0ZWZln4ZXD0
nK96Pv78b7GwRxsBrT3qHFEMEK60B6lMK61shJxFMehb6Nh4UXVth6J295WmphsK
me53CPf5AkEAxdHcdE3ofZwiEKjV3or9aSinZA+AjUw8AqlDxkIS3EGx9qkdQWv+
2tVHJDzlRv68PmkpFotWZyBfKbbKEwzKhwJBALt5ON3FG3X5Tl4yaR9f9TzcDKS4
cvWmUBk7etl1a9lip6s7AM4fkgKBY76Lg0sE8mzVsz09l95gLSIUkckQ/WkCQQC7
BpvAFfxt7ZTDXWy+d3f42SfRUVq/vEisV22tXsDIHxBrXR48wSb1rFkTaMN4aNR+
yRvApcHtxExUeu34Lsq3AkB3HOVsRBj1UlZluiScIEfk1PX2gd84/NBbxT/mhrqi
/wb8sw7ltPobNN7vxlSu5bZG3EfjgEyCCv4EcLNB/uY6
-----END RSA PRIVATE KEY-----
-----BEGIN RSA PRIVATE KEY-----
MIICXgIBAAKBgQDqvM6BgcFGPrwR2A8tnphtH30ruwvE3RBPZk0CUzuqh7BQrPsr
oGNxP0D6ulWg/yWn25ovWjm3ksZ2TaD1PA7PVb3FbzYI3kIQIPFDX6przLwC+faH
J9tqFL1tiMUhjV7Mu8HXx44hTCA8vVbe/GwHn8y1sIZ3FIZnqAlpaFE75QIDAQAB
AoGBAJCHBWKpoHV+pM8bx2SgNFtjuu7U8I8aSTOJ2jpnQuJhPwa9KryWuQN+HaUC
WzyQPAAY7tre45CKd1VZwJOdkcOam4gdRUqrLVSXfYojDCOwn7O7Fwql26v2z42G
YNu/6umdQhsnVCpfked43d/sLuZH4keO2BQVZIS7wxUMMlm1AkEA/CEZ2RuL3Sc5
70+cGyDZ3OOfD3k/Szzz4OTA7yVFoqq6cpepWYYeJKGpno53qeg+WxHusq9TbWBS
1T3UoFz+fwJBAO5XWpiMwAKYg1GtAxkgszIDnkj9Vhe/AL81fvc9KnYFScQQAiZl
PN7MopH0n/oQM8jnXmkusQOmzpVlYBB0W5sCQQCDv7BIGPLfH45QlSMXsfTmTjNh
3JPMdw9hZ2fCD5HxzJEdLE8cLs81iRyfdAbnzCo5YIeA68kGkJz4PRUMr0t1AkBC
hfcvZPmiv9bHUTbwKIRbjU78qFkDP7iBpfjOITBcyJUSODWhadhXh15IxrJwJV2O
0aU0Tmfx0PkQEb+CWDfJAkEAzJPemI3yVYqXG2POBolG5gK2VkHEw7QCQOmMK60Z
+3H7U9F/AvoM3zpRujHBdRxdZlPSrCvbxhyavYhNXDqnjg==
-----END RSA PRIVATE KEY-----
Why the hell N is not equal to p * q ?
Confirmed with the key provided. However, I could not duplicate when generating my own key with openssl genrsa 1024.
$ ./test-rsa.exe
***** P *****
12716592588957205057720227362856602359162165918588008158928004904780617816265357
754968000322907349867949577092305558696339499022301055839537975977118688137
***** Q *****
10059832080410675679274931119486090017360564066559599189867309386706046720813347
145402059918876964980032136051476889631968099168811652389989474036177869729
***** N *****
12793124891325327128971650020563999246628465128785735817714525182531281036799314
77808216241640625923377085054862755880280251221289282252666015910733318035804933
41719724935049328478344297205955905466581637169109448199715137939448946445804542
355907923908845024638480376219852266194827768486624319018352514599977
*** Calc N ***
12792678607990434048632475001531065755874366303681660462967024860494524785586521
24218714399928148249644594040544628864191685952244681103581135994857552437185369
35880977456835036272916419632947427885989469252242704342884476060911074859116149
906854382812141105735147419775039435625802885168567201322191763704873
$ cat test-rsa.c
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <openssl/bn.h>
#include <openssl/evp.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
const char s_key[] = "-----BEGIN RSA PRIVATE KEY-----\n"
"MIICXAIBAAKBgQC2Lh4HLcCR76Wv3oXl6sZ7pv8l9b/66H+I6Bb86tz8RhWCmTCG\n"
"xPVgtZ+w9WutU/rqBHHZOpotX4QDksRD8dRFh6a3HwkIFQdTcDoiD39yNP8F02Gd\n"
"dAl8p/URC5jNCLMSfUK38wMocmoI1I5vqdMNrzUnOup18rl4089Z+faMKQIDAQAB\n"
"AoGBAJrL4z5iWiengxqV8yETBeU8WcJft+n0dapXzHDNAUo8Izr+AIYEBp1Ot4se\n"
"f4igu6zuae80JJ45c2u14p/5dWzN9/URmhTP8xLGjGCjltOJLLyhBPP+ZsLjqu6l\n"
"57MNV6jDqDLdRC66w4NMRCN3FACxcldIC5L6B9OA7UvO1ugBAkEA8s1o6BvufTeD\n"
"ktyOMfW0ZeLGk/6EXp8nf7BIzYhAAPtSt8DegnfYFx2XDgKnYSB15dTDIDMe/KaA\n"
"GcuUb/ZjiQJBAMATb1fFdl7PGccVPgeTaupJayHPySc9PSsACV6VIAnpcU/3NZzd\n"
"MkdIL/JsOsD+1M9uQJqvRZO4qQdjcR5Om6ECQEJGgYlB/pJdcePHomTOvcRF55CE\n"
"G9u8M8rt8qFvvJDICWcxFUulrO16XT4syUWA1825it2iNqYeSL9By63YIokCQBnm\n"
"RPw71xM/r8UleyDAYwlGbxi3EPOmkUnsDldfmltby/ixZ9xIA1CTTkvNBjsh4YY6\n"
"4qE5AxPBMaGaahVhGiECQHyQvXUNE2IUco+ZwmmLnb2ey1s5tBg7i0lEZG47G7GV\n"
"o+yKdJHpToJD8eRJA/2D+pMhQIZm8X/XDIoi1AQ/TRY=\n"
"-----END RSA PRIVATE KEY-----\n";
int main(int argc, char* argv[])
{
UNUSED(argc), UNUSED(argv);
int rc;
FILE* fd = NULL;
EVP_PKEY* pkey = NULL;
RSA* rsa = NULL;
BIGNUM* n = NULL;
BN_CTX* ctx = NULL;
fd = fopen("./key.pem", "w+");
if(fd == NULL) exit(1);
rc = fwrite(s_key, 1, sizeof(s_key), fd);
if(rc != sizeof(s_key)) exit(2);
rc = fseek(fd, 0, SEEK_SET);
if(rc != 0) exit(3);
pkey = PEM_read_PrivateKey(fd, NULL, NULL, NULL);
if(pkey == NULL) exit(4);
rsa = EVP_PKEY_get1_RSA(pkey);
if(rsa == NULL) exit(5);
#if 0
fprintf(stdout, "\n***** RSA *****\n");
RSA_print_fp(stdout, rsa, 0);
#endif
fprintf(stdout, "\n***** P *****\n");
fprintf(stdout, "%s\n", BN_bn2dec(rsa->p));
fprintf(stdout, "\n***** Q *****\n");
fprintf(stdout, "%s\n", BN_bn2dec(rsa->q));
fprintf(stdout, "\n***** N *****\n");
fprintf(stdout, "%s\n", BN_bn2dec(rsa->n));
n = BN_new();
if(!n) exit(6);
ctx = BN_CTX_new();
if(ctx == NULL) exit(7);
rc = BN_mul(n, rsa->p, rsa->q, ctx);
if(rc != 1) exit(8);
fprintf(stdout, "\n*** Calc N ***\n");
fprintf(stdout, "%s\n", BN_bn2dec(n));
BN_CTX_free(ctx);
BN_free(n);
RSA_free(rsa);
EVP_PKEY_free(pkey);
fclose(fd);
return 0;
}
Hi I've tested all 6 private keys you provided in EDIT with this command
$ openssl rsa -check -in privkey
and all of them returns RSA key ok. Except the first one, it returns RSA key error: n does not equal p q.
My answer to your question
Why the hell N is not equal to p * q ?
is: there's no way N is not equal to p*q. The first key has probably been modified, or has been changed during transmission, so it doesn't pass the rsa check test. Digging into the openssl source code, we can see that openssl genrsa command is carried out by
int rsa_builtin_keygen(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb)
in /crypto/rsa/rsa_gen.c. At ln:289, the modulus n is calculated with
/* calculate n */
if (!BN_mul(rsa->n,rsa->p,rsa->q,ctx)) goto err;
which means n=p*q. You should look for other possibilities that cause your problem, rather than casting doubt on genrsa command.
I have an ASN.1 x509 byte array that contains the modulo and the public key of an RSA pair. My goal is to do whatever it takes to use this to encrypt a string. I'm trying to use openssl in objective-c to accomplish this. Whenever I try to get an RSA object using d2i_X509, it returns null. I'm willing to switch to a different library if I can't accomplish this using openssl. Please help me find something that works.
You generally would not encrypt a string using the public key of an X.509 directly. Instead you would generate a strong random(of a specific quality) key; use normal symmetric encryption (such as AES) and then encyrpt the string with that. You then encrypt the random key with the X.509.
Consult a good PKI/Crypto book (e.g. http://www.amazon.com/Applied-Cryptography-Protocols-Algorithms-Source/dp/0471117099) as to why (sections on key leakage, bit-flipping, padding and (re)encrypting twice).
If you really insist on doing this -have a look at https://github.com/dirkx/smime-add-encryption-for-recipient/blob/master/smime-add-encrypt/main.c its pkcs7_encode_rinfo function.
x509cert = ... something to read your x509 byte array in.
unsigned char *stuff = "Some zecret string";
int stufflen = strlen(stuff);
EVP_PKEY *pkey;
EVP_PKEY_CTX *pctx = NULL;
assert(pkey = = X509_get_pubkey( x509cert));
assert(pctx = EVP_PKEY_CTX_new(pkey, NULL));
assert(EVP_PKEY_encrypt_init(pctx)==1);
assert((EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_ENCRYPT
EVP_PKEY_CTRL_PKCS7_ENCRYPT, 0, ri)==1);
size_t eklen;
assert(EVP_PKEY_encrypt(pctx, NULL, &eklen, stuff, stufflen)==1);
ek = OPENSSL_malloc(eklen);
assert(ek);
unsigned char *ek = NULL;
assert((EVP_PKEY_encrypt(pctx, ek, &eklen, key, keylen)==1);
printf("Encrypted blurp: ");
for(int i = 0; i < eklen; i++) {
printf("0x%02X ", ek[i];
};
printf("\n");
exit(0);