RSA and .PEM file Conversion to use in php - php

I generated my own RSA keys at 2048bits using a C++ library and I have all the keys in an array.
I mean N, E, D, p, q, dP, dQ, qInv.
I want to use them in php to decrypt an incoming message to my page.
The most suggested solution around is to use OpenSSL which needs a .pem file and cannot load my Keys in the plain format (including the CRT).
Here is an example of my public Modulus N
[HEX RSA - N-LEN 256]::9FD8DAD3365447AFAC07E8A1D2D729DE099C6CCFD3861F6B78EBF588C2CD6E2D2FCE8A368DF9959E94E9BF463AC12E084B69CF7591FB48D4F46A25C3370779BC57FA8D2F41E5507B6DDC767E5174426B13AB52EE06B1FAA033DE0829EEDA38C89E51823A12214E76F723D09A26A733226A4F650B362130730288A9A49B7E65195E37A78F806D3ED322DFBED83354B609CE08999397E5747389D7631CA79536915C289E27FAF8821A454CF5A238C21CA0F783E4177C387CABEE00B7335F2C1EE5B69100C14320932C3F953C11A4762C964212F09666C8DDE622CC4E3FDB79154025E30B386591DA3499AFC010680FF9648D66596F15ACABBEECE08E38D90E04E4
[HEX RSA - E-LEN 4]::00010001
The other elements of the key I keep them obviously secret.
If I try to convert them using the online conversion tools from XML to .PEM I format them in base64:
<RSAKeyValue>
<Modulus>n9ja0zZUR6+sB+ih0tcp3gmcbM/Thh9reOv1iMLNbi0vzoo2jfmVnpTpv0Y6wS4IS2nPdZH7SNT0aiXDNwd5vFf6jS9B5VB7bdx2flF0QmsTq1LuBrH6oDPeCCnu2jjInlGCOhIhTnb3I9CaJqczImpPZQs2ITBzAoippJt+ZRleN6ePgG0+0yLfvtgzVLYJzgiZk5fldHOJ12Mcp5U2kVwonif6+IIaRUz1ojjCHKD3g+QXfDh8q+4AtzNfLB7ltpEAwUMgkyw/lTwRpHYslkIS8JZmyN3mIsxOP9t5FUAl4ws4ZZHaNJmvwBBoD/lkjWZZbxWsq77s4I442Q4E5A==</Modulus>
<Exponent>AQAB</Exponent>
</RSAKeyValue>
I used this site to test it: https://superdry.apphb.com/tools/online-rsa-key-converter
which bases the conversion on BouncyCastle library.
The online tools they return me invalid parameter while if I use an OpenSSL generated file it works ok:
Plain N Key generated by OpenSSL:
00b122bfa082ee36df33f4cada576f1f5e9a653db95c9deecfa48863507eebce356e937f783a9c58e5d1ed60d1fa19743c4b5d6830f684f7a100e1cb7037f86aab100a840d6b6391008c9e3002db5f1370170719fdfae4c46ff6af1a398a5f7f0c9c006dec7a298c697040c91375d2a400ed71d89bd83b2190487ee6e939b521bf1e97493565e46bc42160e985f0c1d374ad87d76a8d205b3e638f1b544fc946fa34564c7835e33b7187bd4bab214054a3f053e0a4c24fefe13ae889773dcfb08b29cffff25acf486e88f7da5949bf413c89160a323a4874e9df1eb961084e08ccc190102ac42b7be0f1d454f8d3cd31d64570d71a40f3cbd58725f03770da8399
base64 Encrypted
ALEiv6CC7jbfM/TK2ldvH16aZT25XJ3uz6SIY1B+6841bpN/eDqcWOXR7WDR+hl0PEtdaDD2hPehAOHLcDf4aqsQCoQNa2ORAIyeMALbXxNwFwcZ/frkxG/2rxo5il9/DJwAbex6KYxpcEDJE3XSpADtcdib2DshkEh+5uk5tSG/HpdJNWXka8QhYOmF8MHTdK2H12qNIFs+Y48bVE/JRvo0Vkx4NeM7cYe9S6shQFSj8FPgpMJP7+E66Il3Pc+wiynP//Jaz0huiPfaWUm/QTyJFgoyOkh06d8euWEITgjMwZAQKsQre+Dx1FT4080x1kVw1xpA88vVhyXwN3Dag5k=
XML Formatted for conversion:
<RSAKeyValue>
<Modulus>ALEiv6CC7jbfM/TK2ldvH16aZT25XJ3uz6SIY1B+6841bpN/eDqcWOXR7WDR+hl0PEtdaDD2hPehAOHLcDf4aqsQCoQNa2ORAIyeMALbXxNwFwcZ/frkxG/2rxo5il9/DJwAbex6KYxpcEDJE3XSpADtcdib2DshkEh+5uk5tSG/HpdJNWXka8QhYOmF8MHTdK2H12qNIFs+Y48bVE/JRvo0Vkx4NeM7cYe9S6shQFSj8FPgpMJP7+E66Il3Pc+wiynP//Jaz0huiPfaWUm/QTyJFgoyOkh06d8euWEITgjMwZAQKsQre+Dx1FT4080x1kVw1xpA88vVhyXwN3Dag5k=</Modulus>
<Exponent>AQAB</Exponent>
</RSAKeyValue>
Result
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsSK/oILuNt8z9MraV28f
XpplPblcne7PpIhjUH7rzjVuk394OpxY5dHtYNH6GXQ8S11oMPaE96EA4ctwN/hq
qxAKhA1rY5EAjJ4wAttfE3AXBxn9+uTEb/avGjmKX38MnABt7HopjGlwQMkTddKk
AO1x2JvYOyGQSH7m6Tm1Ib8el0k1ZeRrxCFg6YXwwdN0rYfXao0gWz5jjxtUT8lG
+jRWTHg14ztxh71LqyFAVKPwU+Ckwk/v4TroiXc9z7CLKc//8lrPSG6I99pZSb9B
PIkWCjI6SHTp3x65YQhOCMzBkBAqxCt74PHUVPjTzTHWRXDXGkDzy9WHJfA3cNqD
mQIDAQAB
-----END PUBLIC KEY-----
And this is OK.
Does anybody understand why this is not working in my case?
Another point:
I exported OpenSSL N modulus Key and I noticed that it is made of 257 bytes instead of 256 and compared with two keypairs they both starts with 00 which is obviously too wrong.
The bottom line is how can I easily take my HEX plain keys values and encapsulte them into a PEM file or the way around how can I get the correct plain HEX keys values generated by OpenSSL and use them in my C Library (using the .PEM in php)?
Added:
Given that this is the RSA Key structure:
RSAPrivateKey ::= SEQUENCE {
version Version,
modulus INTEGER, -- n
publicExponent INTEGER, -- e
privateExponent INTEGER, -- d
prime1 INTEGER, -- p
prime2 INTEGER, -- q
exponent1 INTEGER, -- d mod (p-1)
exponent2 INTEGER, -- d mod (q-1)
coefficient INTEGER, -- (inverse of q) mod p
otherPrimeInfos OtherPrimeInfos OPTIONAL
}
If I make an inspection with ASN.1 Editor it clearly shows me:
That the Key length of N is 257 Bytes instead of 256 and prime1, prime2 and exponent1 are made of 129 bytes instead of 128.
Super confusing for me....

Related

How to sign ECDSA signature and encode to DER format in hex in php?

How to sign the Tx data including ETH Keccak256 hashed addresses signature with secp256k1 (ECDSA) keys and encode to DER format in hex and verify in php?
I want to use only php libraries come with, openssl and others, to make secp256k1 private and public keys, sign, and convert to DER format in hex for making a sample of my cryptcoin.
Ethereum addresses are made by secp256k1 EDSA keys, hash the 256 bits/64 character pubic key made from the private key with Keccak256 (sha-3-256) hash algorithm to calculate hash, then take last 40 characters from the hash string in hex, add checksum, and add x0 prefix to the hashed string.
The example is shown in github.com/simplito/elliptic-php repo as toDER() function in elliptic-php/lib/EC/Signature.php. The library is using BN-php, but I want to use only php library, openssl and others.
// https://github.com/simplito/elliptic-php ECDSA sample
<?php
use Elliptic\EC;
// Create and initialize EC context
// (better do it once and reuse it)
$ec = new EC('secp256k1');
// Generate keys
$key = $ec->genKeyPair();
// Sign message (can be hex sequence or array)
$msg = 'ab4c3451';
$signature = $key->sign($msg);
// Export DER encoded signature to hex string
$derSign = $signature->toDER('hex');
openssl_pkey_new() and openssl_sign() functions can make new secp256k1 private and public keys and sign, but can not convert the public key to DER format in hex to make address by hashing keccak256 algorithm .
Signing Tx hash requires from/to ETH addresses in JSON string Tx data {address:{to:address1,from:address2},amount:0,timestamp:timestamp tx, hash:sha256hash, previousHash:hash, difficulty:2...} and openssl_pkey_new() openssl_pkey_export() made private and public keys are needed to make ETH address.
Since, openssl_pkey_new() openssl_pkey_export() for OPENSSL_KEYTYPE_EC return DER bin keys, I need to convert them to hex.
I have tried openssl_pkey_new() and openssl_sign() functions but I can not convert to DER format in hex with simple function.
openssl_pkey_new() function to make new secp256k1 key pairs, just
shown in Generating the 256bit ECDSA private key question.
$config = [
"config" => getenv('OPENSSL_CONF'),
'private_key_type' => OPENSSL_KEYTYPE_EC,
'curve_name' => 'secp256k1'
];
$res = openssl_pkey_new($config);
if (!$res) {
echo 'ERROR: Fail to generate private key. -> ' . openssl_error_string();
exit;
}
// Generate Private Key
openssl_pkey_export($res, $priv_key, NULL, $config);
// Get The Public Key
$key_detail = openssl_pkey_get_details($res);
$pub_key = $key_detail["key"];
echo "priv_key:<br>".$priv_key;
echo "<br><br>pub_key:<br>".$pub_key;
Link
And sign with the key.
openssl_sign($hashdata, $signature, $private_key);
Is there any way, with php libraries, to convert the keys to DER in hex?
Okay, now I know what you want I've looked into this, and unfortunately I think you're out of luck. First to clarify, for Ethereum you want the signature in DER and the key format can vary depending on your software, but for an Ethereum account address you do NOT want the key in DER. Specifically an address is computed by:
represent the publickey point as raw X,Y coordinates, with no metadata like DER or even a single byte like X9.62 and no encoding like base64 or hex
take a Keccak256 hash and take the last 20 bytes, which can be represented (e.g. displayed) in hex with 0x prefixed for a total of 42 characters
For step 1, the keys used by OpenSSL, and thus by php's builtin module, are PEM format, as you see in your example, which consists of an ASN.1 (DER or sometimes BER) body encoded in base64 with linebreaks and header/trailer lines. Specifically the publickey is in the format defined by RFC7468 section 13 whose content is the SubjectPublicKeyInfo structure defined by X.509 and PKIX i.e. RFC5280 4.1.2.7 whose contents for a particular algorithm is defined in other standards; the case here, X9-style EC, is defined in RFC3279 2.3.5 and simplified by RFC5480 2.2 which reference X9.62 and SEC1. (Whew!) While these standards allow several options, OpenSSL in PHP always uses X9.62-uncompressed point format and DER encoding, so for this curve the data you need for Ethereum is simply the last 64 bytes of the DER decoded from the PEM:
$der=base64_decode(str_replace(array("-----BEGIN PUBLIC KEY-----\n","-----END PUBLIC KEY-----\n"),"",$pub_key));
$raw=substr($der,-64);
But step 2 is a problem. Although SHA3 and SHAKE as standardized in FIPS202 are instances of Keccak, the hash Ethereum uses is a different and nonstandard instance of Keccak, which OpenSSL does not implement, therefore neither does php by itself (without adding a library).

PHP RSA encryption openssl issue

I have been racking my brain. I am using the latest version of php 7. I can get rsa working with short text, however long text seems to not work. I read to use openssl_seal/open.. when I demoed the code on a test page it works great.. when I put it into practice with mysql its not working the way its supposed to..
Encryption code:
$messageiv = openssl_random_pseudo_bytes(32);
openssl_seal($_POST[$_SESSION['message']], $encryptedmessage, $ekeys, array($_SESSION['recipient_publickey']), "AES256", $messageiv);
openssl_seal($_POST[$_SESSION['subject']], $encryptedsubject, $ekeys, array($_SESSION['recipient_publickey']), "AES256", $messageiv);
The above is then base91_encoded and stored into blobs/varchar.
To decrypt it
openssl_open(base91_decode($row['messagesubject']), $decryptedsubject, $ekeys[0], $_SESSION['privatersakey'], "AES256", base91_decode($row['messageiv']));
openssl_open(base91_decode($row['messagebody']), $decryptedbody, $ekeys[0], $_SESSION['privatersakey'], "AES256", base91_decode($row['messageiv']));
The above variables $decryptedsubject and $decryptedmessage are blank.
I had this issue before using openssl_public/private key encrypt/decrypt and added the padding, this worked, however with long text it won't encrypt/decrypt....
Any assistance would be great...
I can get rsa working with short text, however long text seems to not work.
This is expected. RSA only operates on short inputs. If you want to encrypt a long message with RSA, you need to do one of two things:
Break your message into several distinct chunks and encrypt them separately. This is slow, inefficient, and insecure. (Attackers can drop or reorder chunks.)
Use a secure construction combining RSA and AES, like so.
Thus, you end up with something like this:
Encryption
Generate a random 32-byte key, k.
Encrypt k with your RSA public key to get C.
Calculate the HMAC-SHA256(C, k) to get the message key m.
Encrypt your message (P) with m, using AES-256-GCM to get D.
Return C and D.
Decryption
Generate a random dummy key, which we'll call k'.
Decrypt C using your RSA private key, to obtain k (one-time AES key).
If step 2 failed, use a constant-time algorithm to swap k out for k'.
Calculate the HMAC-SHA256(C, k) to get the message key m.
Decrypt D using m.
Return the decrypted plaintext (or fail because of the authentication tag).
I read to use openssl_seal/open.. when I demoed the code on a test page it works great.. when I put it into practice with mysql its not working the way its supposed to..
First, consider using libsodium instead.
Whether or not you continue to use OpenSSL, you probably want to base64-encode your output (and make sure you're storing data in a text field rather than a short varchar).

PHP create ECDSA signature and verify with Golang

I try to make the app with PHP that creates ECDSA signature for some document and that signature is verified with Golang app.
I use private keys generated with openssl tool. It is prime256v1 curve key. Created with the command:
openssl ecparam -name prime256v1 -genkey -noout -out prime256v1-key.pem
In PHP i create signature using openssl_sign function.
And all my attempts to verify the signature with Golang fail. In Golang use the crypto/ecdsa, crypto/elliptic packages.
There is my code.
PHP
<?php
$stringtosign = "my test string to sign";
// Privcate key was geerated with openssl tool with the command
// openssl ecparam -name prime256v1 -genkey -noout -out prime256v1-key.pem
$cert = file_get_contents('prime256v1-key.pem');
$prkey = openssl_pkey_get_private($cert);
// we sign only hashes, because Golang lib can wok with hashes only
$stringtosign = md5($stringtosign);
// we generate 64 length signature (r and s 32 bytes length)
while(1) {
openssl_sign($stringtosign, $signature, $prkey, OPENSSL_ALGO_SHA256);
$rlen = ord(substr($signature,3,1));
$slen = ord(substr($signature,5+$rlen,1));
if ($slen != 32 || $rlen != 32) {
// try other signature if length is not 32 for both parts
continue;
}
$r = substr($signature,4,$rlen);
$s = substr($signature,6+$rlen,$slen);
$signature = $r.$s;
break;
}
openssl_free_key($prkey);
$signature = bin2hex($signature);
echo $signature."\n";
Golang
package main
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/md5"
"encoding/hex"
"fmt"
"io"
"io/ioutil"
"math/big"
"crypto/x509"
"encoding/pem"
)
func main() {
stringtosign := "my test string to sign"
// This is outpur of PHP app. Signature generated by PHP openssl_sign
signature := "18d5c1d044a4a752ad91bc06499c72a590b2842b3d3b4c4b1086bfd0eea3e7eb5c06b77e15542e5ba944f3a1a613c24eabaefa4e2b2251bd8c9355bba4d14640"
// NOTE . Error verificaion is skipped here
// Privcate key was geerated with openssl tool with the command
// openssl ecparam -name prime256v1 -genkey -noout -out prime256v1-key.pem
prikeybytes, _ := ioutil.ReadFile("prime256v1-key.pem")
p, _ := pem.Decode(prikeybytes)
prikey, _ := x509.ParseECPrivateKey(p.Bytes)
signatureBytes, _ := hex.DecodeString(signature)
// make MD5 hash
h := md5.New()
io.WriteString(h, stringtosign)
data := h.Sum(nil)
// build key and verify data
r := big.Int{}
s := big.Int{}
// make signature numbers
sigLen := len(signatureBytes)
r.SetBytes(signatureBytes[:(sigLen / 2)])
s.SetBytes(signatureBytes[(sigLen / 2):])
curve := elliptic.P256()
// make public key from private key
x := big.Int{}
y := big.Int{}
x.SetBytes(prikey.PublicKey.X.Bytes())
y.SetBytes(prikey.PublicKey.Y.Bytes())
rawPubKey := ecdsa.PublicKey{Curve: curve, X: &x, Y: &y}
v := ecdsa.Verify(&rawPubKey, data, &r, &s)
if v {
fmt.Println("Success verify!")
return
}
fmt.Println(fmt.Sprintf("Signatire doed not match"))
}
What do i do wrong? Can anyone show me working example where Golang verifies signatre created with PHP?
I tried to use different versions in openssl_sign instead of OPENSSL_ALGO_SHA256 . Tried OPENSSL_ALGO_SHA1, OPENSSL_ALGO_SHA512
The problem with your code seems to be, that you hash the string in PHP using MD5 before signing it using OPENSSL_ALGO_SHA256, which hashes what you sign (the MD5 hash) again, while in your Go program, you only have the first of these 2 hashes. To fix this, I would remove the MD5 step in the PHP code and replace the h := md5.New() line in your code with the hash used by your signature algorithm (h := sha256.New() in your example).
To elaborate a bit more on what theses signing functions do, I would first like to break signing and verifying down into the following steps:
Signing:
Hash the message
Encrypt the message's hash using the private key (this encrypted hash is the signature)
Verifying:
Hash the message
Decrypt the signature using the public key (this yields the hash which was encrypted while signing).
Compare the calculated and decrypted hashes. If they match, then the signature is correct.
Now the call to openssl_sign in your PHP code, does all the signing steps, while the call to ecdsa.Verify in Go, only does the second and third step of the verification process. And this is why it takes a hash as the second argument. So to verify a signature, you must implement the first verification step yourself, namely generating the hash.
You must use the same hashing algorithm while signing and verifying, therefore you must use SHA256, not MD5, in your Go code (as you sign using OPENSSL_ALGO_SHA256), otherwise the hashes will (generally) not match.
Also, I would recommend to not use MD5 for signatures, as it is no longer considered collision resistant (a hash collision is, when you have 2 different strings/files/... with the same hash). For more details about that, you can check the Wikipedia article on MD5, specifically the section "Collision vulnerabilities". This is a problem, as 2 messages with the same MD5 hash, will also have the same signature and an attacker could use the signature generated for one of the strings to trick you into thinking the other was signed (and therefore trust it).
Additionally, ecdsa.PrivateKey can give you the corresponding public key, and you can call ecdsa.Verify like this:
ecdsa.Verify(&prikey.PublicKey, data, &r, &s)
This saves you the trouble of copying all the data from the private key to a new object.

RSA Modulus and Exponent to OpenSSL pem Format

I have a RSA Public Key in this format:
OpenSSLRSAPublicKey{modulus=9ee9f82dd8429d9fa7f091c1d375b9c289bcf2c39ec57e175a2998b4bdd083465ef0fe6c7955c821b7e883929d017a9164a60290f1622f664a72096f5d2ffda7c7825c3d657c2d13d177445fa6cdd5d68b96346006a96040f5b09baae56d0c3efeaa77d57602f69018f5cefd60cb5c71b6b6f8a4b0472e8740367266917d8c13,publicExponent=10001}
So, I have the modulus and the exponent.
How can I convert this in a format that is accepted by openssl_encrypt() in PHP?
I have searched on Google and didn't find anything good. Isn't there an easy way to format it?
Assuming you mean openssl_public_encrypt() instead of openssl_encrypt(), then try this (using phpseclib 1.0):
<?php
include('Crypt/RSA.php')
include('Math/BigInteger.php');
$rsa = new Crypt_RSA();
$rsa->loadKey(array(
'n' => new Math_BigInteger('9ee9f82dd8429d9fa7f091c1d375b9c289bcf2c39ec57e175a2998b4bdd083465ef0fe6c7955c821b7e883929d017a9164a60290f1622f664a72096f5d2ffda7c7825c3d657c2d13d177445fa6cdd5d68b96346006a96040f5b09baae56d0c3efeaa77d57602f69018f5cefd60cb5c71b6b6f8a4b0472e8740367266917d8c13', 16),
'e' => new Math_BigInteger('10001', 16)
));
echo $rsa;
Altho that said, if you're gonna use phpseclib to convert the key, why not use it to encrypt whatever it is that you're trying to encrypt as well?:
//$rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
$rsa->encrypt('plaintext');
No, there isn't any way to do this. Public/private keys can only be used in asymmetric cryptography. openssl_encrypt() requires symmetric cryptography.
openssl_public_encrypt() which you need for asymmetric cryptography wants a pubic key resource. This can be obtained using openssl_pkey_get_public().
Now, openssl_pkey_get_public() needs a PEM file. The docs describe it as:
an X.509 certificate resource
a string having the format file://path/to/file.pem. The named file must contain a PEM encoded certificate/public key (it may contain both).
A PEM formatted public key.
So you need to create a PEM file from the public key configuration you have in your question. The modulus and exponent you have are enough to do this.
There are several examples on the internet on how to archive this. Have a look at:
Generate .pem RSA public key file using base 10 modulus and exponent?
rawrsa (https://github.com/JonathonReinhart/rawrsa)
how to convert raw modulus & exponent to RSA public key (.pem format)
Basically you need to create a "ASN1-formatted text file" and employ some openssl commands.

Encrypt password (RSA) with public key

I'm having serious problems with what I was hoping would be a simple call to PHP's
openssl_public_encrypt();
Sadly, I get an invalid public key warning.
My goal is to simply RSA encrypt a users password using public key provided by their API which currently looks like this:
+Tir6+unMOaQ5tHqjjjwnlAMhccnCSMFEi3a0mhIxbW+O/GukjomGyzckQT2h0Ys70JezHbNq5YS3sYkNF29kCkz4HuNfy9eEjE/clA9/zyfT8ZcbnusLcLz2xNgbTp62fQdzBnReI5+dpj/N24krYvHaYIr8ACxDqBv2TR3E9M=AQAB
Apparently a working implementation using the same service I'm trying to use found a solution with these steps:
Extract the modulus and exponent from the public key
Re-constructs the key in the MS PUBLICKEYBLOB format
Call OpenSSL to convert the key to PEM format
Load the PEM public key from the converted file
Encrypts the password (after converting to UTF-16LE)
However not only that I dont know if its possible to do in PHP , I think there Must be an easier way!
One post I saw hinted that the exponent may come after the last = sign (so AQAB) but I don't know if this is reliable.
Something like this do what you want?:
<?php
$key = '+Tir6+unMOaQ5tHqjjjwnlAMhccnCSMFEi3a0mhIxbW+O/GukjomGyzckQT2h0Ys70JezHbNq5YS3sYkNF29kCkz4HuNfy9eEjE/clA9/zyfT8ZcbnusLcLz2xNgbTp62fQdzBnReI5+dpj/N24krYvHaYIr8ACxDqBv2TR3E9M=AQAB';
include('Crypt/RSA.php');
$rsa = new Crypt_RSA();
$rsa->loadKey(array(
'e' => new Math_BigInteger(65537),
'n' => new Math_BigInteger(substr($key, 0, -4), -256)
));
$ciphertext = $rsa->encrypt('password');
echo bin2hex($ciphertext);
?>
This example uses phpseclib, a pure PHP RSA implementation. Although phpseclib does not support the format of the key you posted it does support raw public keys and as such converting to PKCS1 style keys is unnecessar. And the ciphertext's produced by phpseclib are perfectly interoperable with OpenSSL.
OK, so what you need to do:
remove the AQAB part and use the value 65537 for the public exponent
base 64 decode the modulus
create a DER encoding of the public key in PKCS#1 format (see below)
base64 encode the DER encoding using 64 character line length and DOS line endings
add PEM header & footer
use the PEM encoded string to create a public key and finally
encrypt the password
The following ASN.1 spec defines the public key in PKCS#1 format:
RSAPublicKey ::= SEQUENCE {
modulus INTEGER, -- n
publicExponent INTEGER -- e
}
Now the identifier octet or tag of SEQUENCE is 30 in hex, INTEGER is 02 and the length should be specified like this. So you get something like:
30818902818100F938ABEBEBA730E690E6D1EA8E38F09E500C85C727092305122DDAD26848C5B5BE3BF1AE923A261B2CDC9104F687462CEF425ECC76CDAB9612DEC624345DBD902933E07B8D7F2F5E12313F72503DFF3C9F4FC65C6E7BAC2DC2F3DB13606D3A7AD9F41DCC19D1788E7E7698FF376E24AD8BC769822BF000B10EA06FD9347713D30203010001
in hexadecimals. So after base 64 encoding and adding the header and footer line you should get:
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQH5OKvr66cw5pDm0eqOOPCeUAyFxycJIwUSLdrSaEjFtb478a6SOiYbLNyRBPaHRizvQl7Mds2rlhLexiQ0Xb2QKTPge41/L14SMT9yUD3/PJ9Pxlxue6wt
wvPbE2BtOnrZ9B3MGdF4jn52mP83biSti8dpgivwALEOoG/ZNHcT0wIDAQAB
-----END RSA PUBLIC KEY-----
Happy coding.

Categories