As official doc
const crypto = require('crypto');
const sign = crypto.createSign('sha256');
sign.update('some data to sign');
const privateKey =
`-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIF+jnWY1D5kbVYDNvxxo/Y+ku2uJPDwS0r/VuPZQrjjVoAoGCCqGSM49
AwEHoUQDQgAEurOxfSxmqIRYzJVagdZfMMSjRNNhB8i3mXyIMq704m2m52FdfKZ2
pQhByd5eyj3lgZ7m7jbchtdgyOF8Io/1ng==
-----END EC PRIVATE KEY-----`;
console.log(sign.sign(privateKey).toString('hex'));
How can we generate the private key like the below format using crypto module?
`-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIF+jnWY1D5kbVYDNvxxo/Y+ku2uJPDwS0r/VuPZQrjjVoAoGCCqGSM49
AwEHoUQDQgAEurOxfSxmqIRYzJVagdZfMMSjRNNhB8i3mXyIMq704m2m52FdfKZ2
pQhByd5eyj3lgZ7m7jbchtdgyOF8Io/1ng==
-----END EC PRIVATE KEY-----`;
I trying to using createECDH getPrivateKey,but not the format I want.And using this format to sign will cause
Error: error:0906D06C:PEM routines:PEM_read_bio:no start line
const crypto = require('crypto');
const bob = crypto.createECDH('secp256k1');
bob.generateKeys();
const privateKey = bob.getPrivateKey()
console.log(privateKey)
I was try to convert it using
const privateKey = bob.getPrivateKey().toString('base64');
and add comment to head and tail,make it look like this
`-----BEGIN EC PRIVATE KEY-----
pQhByd5eyj3lgZ7m7jbchtdgyOF8Io/1ng==
-----END EC PRIVATE KEY-----`;
But this still not works
How can I generate an valid ECC pem in node.js using Crypto module?
Related
In Ethereum, the wallet address is the last 20 bytes of the keccak256 hash of the public key of the wallet.
I am working with Hyperledger Fabric EVM, and I would like to know which is the mechanism that is used to generate the address from the public key.
I applied keccak256, sha256, and sha-3 256 to my public key, but I didn't get the correct address...
It is my private key in pem format:
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgjUp+AWrFlIVp13Dl
rpm/Uu2M++ZhOC4AbmjWdsofP7ihRANCAARWnvMdt+149KEt9yPKoLHG98lL5wPe
cGVMBMxsJhz3JLBSQlBCfLMz8fe5vIng4N7TGYt66P2HNeG/fLjwt7jI
-----END PRIVATE KEY-----
It is my public key in pem format:
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEVp7zHbftePShLfcjyqCxxvfJS+cD
3nBlTATMbCYc9ySwUkJQQnyzM/H3ubyJ4ODe0xmLeuj9hzXhv3y48Le4yA==
-----END PUBLIC KEY-----
It is my public key in hex format:
Public_key = 0x04569ef31db7ed78f4a12df723caa0b1c6f7c94be703de70654c04cc6c261cf724b0524250427cb333f1f7b9bc89e0e0ded3198b7ae8fd8735e1bf7cb8f0b7b8c8
And it is my address:
13065B11B498911F2A19815035D0AC24457D1BB6
I am using secp256r1
The address is the last 20 bytes of the sha3-256 of 3059301306072a8648ce3d020106082a8648ce3d030107034200 + public_key_hex
In my example, take the last 160 bits (20 bytes) of "result" :
var Public_key = 0x04569ef31db7ed78f4a12df723caa0b1c6f7c94be703de70654c04cc6c261cf724b0524250427cb333f1f7b9bc89e0e0ded3198b7ae8fd8735e1bf7cb8f0b7b8c8
var result = SHA3_256(0x3059301306072a8648ce3d020106082a8648ce3d030107034200 + Public_key)
var address = last_20bytes(result)
console.log("address = ",address);
//address = 13065B11B498911F2A19815035D0AC24457D1BB6
I'm getting an error when verifying an Azure AD generated token. This is the current setup:
I have a token which can be pasted on https://jwt.io, and I can see in the right panel the correct claims. I assume the token is correctly formatted. I can also see in the headers that kid = piVlloQDSMKxh1m2ygqGSVdgFpA and alg: RS256. I set correctly the algo type to RS256 for verification.
I went to https://login.microsoftonline.com/common/discovery/keys to find the public key, and found the same kid = piVlloQDSMKxh1m2ygqGSVdgFpA. So I copied the corresponds public key (the string in the x5c field) and wrapped it into the correct strings to make it PKCS#8. compatible:
-----BEGIN CERTIFICATE-----
MIIDBTCCAe2gAwIBAgIQMCJcgWf4l5xPpeoEwB7DKDANBgkqhkiG9w0BAQsFADAtMSswKQYDVQQDEyJhY2NvdW50cy5hY2Nlc3Njb250cm9sLndpbmRvd3MubmV0MB4XDTE5MTExNTAwMDAwMFoXDTI0MTExNDAwMDAwMFowLTErMCkGA1UEAxMiYWNjb3VudHMuYWNjZXNzY29udHJvbC53aW5kb3dzLm5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANF4YcKZhKTfowwWqZ84RW7bxFNgaSy3Gi85V5uJpU9jMCmZV0VFGptryNFEQ1GESmmuDutgQlkkhjr9ixkOrTA+aFPg6pLn+OG6NYS7nyKgAC1MprLH0bq06y3dH6lQPWQhd3wPP+8UIua9+9JuIfhu9Xs/HhN5cYlT5cEniV0aWuUMxgPAKcG1xolfupYhlOHjFwVN/QOaxcuk3YqGguD+sZ7PiHcJSzFnTkdvD+DtMoW1U6nDf5FuDeAEKJ7JQf7RjiRoViYxZHKrEPHG4iZ+kOhV6DQA16ISTt7ALXVB8gTTF3OvItubk2E3v6sgirgtvdE5Mkd4MTJcO67bgdUCAwEAAaMhMB8wHQYDVR0OBBYEFEXiTeLGkA2LgAjQOrT2KChpgwCgMA0GCSqGSIb3DQEBCwUAA4IBAQA6GqtYZDQzym0yxfL2NnlSbJP/lLhSQOqbPBdN6DWQ/3duk+e08Ix5qy63hzW+qQR0PAkFEcooL5+bdheS66tFJpVejEcqCSKUVvwOUe6GY/ju752dlB7anBB9An362khehCxqydYNS5Igl0rtcP7dKC3ZBn1m2B9ULsyx46iNpfHQHHv9NKU2vVq2CtNc95CFktwjUwlyWMgbfI/DzPX/cC6KnglqsuVVBO7+jIaBmi0XGqudooZkqgIrvnfNMM13Gy78TUNHsCiAQEwZ/L17yNbzotNGxAoPfuXldbD52MQNOsA7WhH+j8qFWY6gZzTN4NpVtuW4m04TCEFexnTz
-----END CERTIFICATE-----
In case it's not visible above, there is a \n after -----BEGIN CERTIFICATE----- and before -----END CERTIFICATE-----
That public key got copied in the public key part of it, and in my code it's the public RSA key.
I also tried formatting using PKCS#1, I didn't get more success
It keeps being invalid. Not even expired, clearly invalid, both on jwt.io and in my code.
Assuming the token is correct, is my methodology correct? I found different tutorials preparing the .pem differently. If my token is incorrect, how can I check that aside of getting claims from it?
You need to generate the public key from modulus and exponent.
You can get them from https://login.microsoftonline.com/{tenantId_or_commom}/discovery/v2.0/keys
Here is a java sample for your reference:
public static PublicKey getPublicKey(String encodedModulus, String encodedExponent) throws NoSuchAlgorithmException, InvalidKeySpecException {
byte[] modulus = Base64.getUrlDecoder().decode(encodedModulus);
byte[] exponent = Base64.getUrlDecoder().decode(encodedExponent);
StringBuilder sb = new StringBuilder();
for (byte b : modulus) {
sb.append(String.format("%02x", b));
}
String sm = sb.toString();
sb = new StringBuilder();
for (byte b : exponent) {
sb.append(String.format("%02x", b));
}
String se = sb.toString();
BigInteger bm = new BigInteger(sm,16);
BigInteger be = new BigInteger(se,16);
KeyFactory rsa = KeyFactory.getInstance("RSA");
PublicKey publicKey = rsa.generatePublic(new RSAPublicKeySpec(bm, be));
return publicKey;
}
public static void main(String[] args) throws Exception {
String modulus = "0XhhwpmEpN-jDBapnzhFbtvEU2BpLLcaLzlXm4mlT2MwKZlXRUUam2vI0URDUYRKaa4O62BCWSSGOv2LGQ6tMD5oU-Dqkuf44bo1hLufIqAALUymssfRurTrLd0fqVA9ZCF3fA8_7xQi5r370m4h-G71ez8eE3lxiVPlwSeJXRpa5QzGA8ApwbXGiV-6liGU4eMXBU39A5rFy6TdioaC4P6xns-IdwlLMWdOR28P4O0yhbVTqcN_kW4N4AQonslB_tGOJGhWJjFkcqsQ8cbiJn6Q6FXoNADXohJO3sAtdUHyBNMXc68i25uTYTe_qyCKuC290TkyR3gxMlw7rtuB1Q";
String exponent = "AQAB";
byte[] bytes = getPublicKey(modulus, exponent).getEncoded();
String encodedString = new String(Base64.getEncoder().encode(bytes));
System.out.println("-----BEGIN PUBLIC KEY-----");
System.out.println(encodedString);
System.out.println("-----END PUBLIC KEY-----");
System.out.println();
}
You will get some outputs as following:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0XhhwpmEpN+jDBapnzhFbtvEU2BpLLcaLzlXm4mlT2MwKZlXRUUam2vI0URDUYRKaa4O62BCWSSGOv2LGQ6tMD5oU+Dqkuf44bo1hLufIqAALUymssfRurTrLd0fqVA9ZCF3fA8/7xQi5r370m4h+G71ez8eE3lxiVPlwSeJXRpa5QzGA8ApwbXGiV+6liGU4eMXBU39A5rFy6TdioaC4P6xns+IdwlLMWdOR28P4O0yhbVTqcN/kW4N4AQonslB/tGOJGhWJjFkcqsQ8cbiJn6Q6FXoNADXohJO3sAtdUHyBNMXc68i25uTYTe/qyCKuC290TkyR3gxMlw7rtuB1QIDAQAB
-----END PUBLIC KEY-----
And then you can use it in jwt.io:
I met a problem of RSA decryption.
First of all, I created a pair of public and private key in openssl(LibreSSL 2.6.4 in OS X 10.14):
genrsa -out rsa_private_key.pem 1024
rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
Then I wrote functions to do encrypt and decrypt. The code looks like:
//rsa.js
const crypto = require('crypto');
exports.encrypt = (data, key) => {
try {
let enc = crypto.publicEncrypt(key, Buffer.from(data));
return enc;
} catch (error) {
console.log('encrypt error:', error);
return null;
}
};
exports.decrypt = (encrypted, key) => {
try {
let dec = crypto.privateDecrypt({'key':key, 'padding': crypto.constants.RSA_PKCS1_OAEP_PADDING }, encrypted);
return dec;
} catch (error) {
console.log('decrypt error:', error);
return null;
}
};
And I run a nodejs app which encrypts a string with public key and decrypts with
private key:
//test.js
const rsa = require('./rsa');
const rsaKeys = require('./rsaKeys');
const plainText = '111111';
const crypted = rsa.encrypt(plainText, rsaKeys.pubKey);
const decrypted = rsa.decrypt(crypted, rsaKeys.privKey);
console.log('crypted:', crypted.toString('base64'));
console.log('decrypted:',decrypted.toString());
It runs well as decrypted is exactly the plain text '111111'. Then I change the last 3 bits of private key mistakenly, for example:
exports.privKey = `-----BEGIN RSA PRIVATE KEY-----
xxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxccc
-----END RSA PRIVATE KEY-----
`;
I continue to run the test.js, and what makes me surprised is that it shows decrypted: 111111.
Later I changed the last 3 bits several times and all can show decrypted correctly. When I changed the first 3 bits of private key, the decrypt runs with the exceptions.
I can't understand why comes such result ad I know little about cypher.
Please point the guide on how to understand it.
Update: add the pair of keys.
exports.privKey = `-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQCWVJtkMDXP1cM6wgOW4aMlHpCg+z0o+mSUTOQwCHJ4Em0x76jm
HsNcFV9svl2KsVZmAvb3CWkNGy/+ST4cKHALMRNZ5hKNcemRH7BSHgBPTNY896Zs
0FIHClsi9J0sWC5dNdVQ02JmU2WPz9XPlVhzaELmlnJ22ecJgpDUwiZFMwIDAQAB
AoGAffe/jiBntxQkV6QjZdcE4iHOh1Z/VUsb5LjZrPYnFT47idCM8udsREkUgQaz
U3huMWTilPaptHXHrYiqJuYrm6xZsSxavsgAgoWSDTwu38PdKQ+HTrGHk6/anhXD
R/qSiS32t5EeAqvgLsxlzyyUYiaExFl/Na9seh3Acm7KMCECQQDIJmyMyBfnlFKt
cD5NTUsg2pTSgaPOmcrx8B+UMudIVzNtFRKyci/t59aPrGJml8ILBzA2QxyJ+tMg
eZdRUNjdAkEAwEdbOVl5Rol66F/NCm3ID5RxeEmVVTo7zLhxmGLSVseATWddlhtJ
iavEtzMDS7aJTDH775RwrQi3S7izWN6tTwJBAL2h0iUMi8GJAVB8UTsSaYUGNAzC
cX4UrnjNxk22cPVUUVAfsChMEec5Skuzy0Nis6GZPO+cZFTCxfg1281aaS0CQHYu
5dlYL3y1oAAYclUIqUE6Qoxm3gzmoD7y14+MnjCMq0XoVNOgrhCarWzVRB9TcQyO
ZIYbvS39/3vhaQskw20CQQCPFDSlrBvUMPJY86SG9fU38nxvKG/6HYYjjmnXeG5M
0rr9oPFSkL4pf2pXpZLtm5iNQoErWntsk9N7rYflH7xj
-----END RSA PRIVATE KEY-----
`;
exports.pubKey = `-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCWVJtkMDXP1cM6wgOW4aMlHpCg
+z0o+mSUTOQwCHJ4Em0x76jmHsNcFV9svl2KsVZmAvb3CWkNGy/+ST4cKHALMRNZ
5hKNcemRH7BSHgBPTNY896Zs0FIHClsi9J0sWC5dNdVQ02JmU2WPz9XPlVhzaELm
lnJ22ecJgpDUwiZFMwIDAQAB
-----END PUBLIC KEY-----
`;
How can I generate a private and public key, use the private key to sign a hash of arbitrary text, then elsewhere use the public key to verify the signature?
Using URSA (Node.js wrappers for OpenSSL crypto):
var ursa = require('ursa');
// Generate RSA private key (public key included)
var keyPair = ursa.generatePrivateKey();
// Convert public key to string
var pub = keyPair.toPublicPem('base64');
// Create buffer from text
var data = new Buffer('Hello, world!');
// Create MD5 hash and sign with private key
var sig = keyPair.hashAndSign('md5', data);
// Elsewhere...
// Create public key object from PEM string
pub = ursa.createPublicKey(pub, 'base64');
// Verify signature - should return true
pub.hashAndVerify('md5', data, sig);
I need to do some encryption in J2ME through sms. The app receives the public key in an sms as String, the same way openssl creates Public key from Private key, this is how the keys are created:
Private Key: openssl genrsa -out privkey.pem 144
Public key: openssl rsa -in privkey.pem -out pubkey.pem
The String is created with something like this, which is the public key:
MGwCAQACEwCxcz+Qk8J6CptiRg6EBpG6SHECAwEAAQISVTLKcDYhh8sTJggObTKI
pdIJAgoA7EwFr5Un3AErAgoAwD8WTwqL0vbTAgoAkuPfVPr/wD/pAgl44rKqfR0z
SRUCCgDDqC/pMSBHTJs=
Now, how to get to the point in a source code to get this public key in a RSAPublicKey ready to be used in a cipher?
To do this:
byte[] plaintext="some text".getBytes();
byte[] encryptedtext;
Cipher cipher=Cipher.getInstance("RSA");
RSAPublicKey pubKey=new RSAPublicKey(????????);
cipher.init(Cipher.ENCRYPT_MODE,pubkey);
cipher.doFinal(plaintext,0,plaintext.length,encryptedtext,0)