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-----
`;
Related
I have run Checkmarx scan on my application . The scan report reports the following on my piece of code.
"Inadequate encryption strength - The application uses a weak cryptographic algorithm, getPrivate() to protect sensitive personal information password"
public String sign(String text) {
try {
KeyPair keyPair = this.getKeyPair();
Signature privateSignature = Signature.getInstance("SHA1withRSA");
privateSignature.initSign(**keyPair.getPrivate()**);
privateSignature.update(text.getBytes(UTF_8));
byte[] signature = privateSignature.sign();
return Base64.getEncoder().encodeToString(signature);
} catch (Exception exp) {
}
}
public KeyPair getKeyPair()
throws Exception {
Key key = this.keyStore.getKey(ALIAS, **this.password.toCharArray()**);
Certificate cert = this.keyStore.getCertificate(ALIAS);
PublicKey publicKey = cert.getPublicKey();
return new KeyPair(publicKey, (PrivateKey) key);
}
Please help me in resolving this issue.
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:
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?
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);