Generate RSA keypair in perl efficently with custom PRNG - perl

I would want to generate a public and private keypair, effciently (fast) in perl, and be able to input random data for myself.
With inputting random data, I of course mean, that the function requires lets say X random bits to generate a public/private keypair of Y bits, and I should be able to supply these X bits to the function.
So idially, the function should look like:
($private, $public) = genRSAkeypair($randomdata, 1024);
and $private then contains:
----BEGIN RSA PRIVATE KEY-----
....
----END ....
and $public contains
----BEGIN RSA PUBLIC and so on...
$randomdata is then just a string of random bits from any random generator. If $randomdata is consistent between instance1 and instance2, instance1 and instance2 should return the same public and private keys.
If you want to know what the use of this is, is that I plan to make a password-based RSA key generation system, without any need to store any keys anywhere. So the key is generated straight out from the password, by using SHA512 chained in a specific way to create static random data.
Of course, the same public and private key must be returned everytime the same password is entered in the system, else the system would be useless.
Any ideas?

I would try Crypt::OpenSSL::RSA, it seems to bind
directly to libssl

Related

What are the main requirements on the RSA 1024 key pair to be usable in javax.crypto.Cipher/BouncyCastle?

While fighting with another problem described Is it possible to use javax.crypto.Cipher RSA 1024 to decrypt the message with the public key? Maybe public key can be used for encryption only? I have observed that javax.crypto.Cipher/BouncyCastle has very harsh constraints on the allowed RSA key pairs. In fact - I have no managed to come up with the RSA key pair that satisfies their requirements. The different error messages were:
java.lang.IllegalArgumentException: RSA publicExponent is even
at com.android.org.bouncycastle.crypto.params.RSAKeyParameters.<init>(RSAKeyParameters.java:28)
at com.android.org.bouncycastle.jcajce.provider.asymmetric.rsa.RSAUtil.generatePublicKeyParameter(RSAUtil.java:48)
at com.android.org.bouncycastle.jcajce.provider.asymmetric.rsa.CipherSpi.engineInit(CipherSpi.java:293)
at com.android.org.bouncycastle.jcajce.provider.asymmetric.rsa.CipherSpi.engineInit(CipherSpi.java:411)
at javax.crypto.Cipher.tryTransformWithProvider(Cipher.java:2984)
at javax.crypto.Cipher.tryCombinations(Cipher.java:2891)
at javax.crypto.Cipher$SpiAndProviderUpdater.updateAndGetSpiAndProvider(Cipher.java:2796)
at javax.crypto.Cipher.chooseProvider(Cipher.java:773)
at javax.crypto.Cipher.init(Cipher.java:1143)
at javax.crypto.Cipher.init(Cipher.java:1084)
javax.crypto.BadPaddingException: error:03000068:bignum routines:OPENSSL_internal:CALLED_WITH_EVEN_MODULUS
at com.android.org.conscrypt.NativeCrypto.RSA_public_encrypt(Native Method)
at com.android.org.conscrypt.OpenSSLCipherRSA$DirectRSA.doCryptoOperation(OpenSSLCipherRSA.java:398)
at com.android.org.conscrypt.OpenSSLCipherRSA.engineDoFinal(OpenSSLCipherRSA.java:316)
at javax.crypto.Cipher.doFinal(Cipher.java:2055)
java.lang.IllegalArgumentException: RSA modulus has a small prime factor
at com.android.org.bouncycastle.crypto.params.RSAKeyParameters.validate(RSAKeyParameters.java:50)
at com.android.org.bouncycastle.crypto.params.RSAKeyParameters.<init>(RSAKeyParameters.java:32)
at com.android.org.bouncycastle.jcajce.provider.asymmetric.rsa.RSAUtil.generatePublicKeyParameter(RSAUtil.java:48)
at com.android.org.bouncycastle.jcajce.provider.asymmetric.rsa.CipherSpi.engineInit(CipherSpi.java:293)
at com.android.org.bouncycastle.jcajce.provider.asymmetric.rsa.CipherSpi.engineInit(CipherSpi.java:411)
at javax.crypto.Cipher.tryTransformWithProvider(Cipher.java:2984)
at javax.crypto.Cipher.tryCombinations(Cipher.java:2877)
at javax.crypto.Cipher$SpiAndProviderUpdater.updateAndGetSpiAndProvider(Cipher.java:2796)
at javax.crypto.Cipher.chooseProvider(Cipher.java:773)
at javax.crypto.Cipher.init(Cipher.java:1143)
I established pretty simple workflow for the generation of key pairs for my tests: I used https://www.csfieldguide.org.nz/en/interactives/rsa-key-generator/ (1024 bits/Format scheme PCKS #1 (base64)) for the generation of pairs and then I copy/pasted public key to the https://lapo.it/asn1js/ and made decoding the public key into 2 integers. I immediately rejected the pair if at least one of the integers was an even number.
But apparently, there are more constraints. What are those constraints? I would be nice to have some (at least partial) list of them so I can implement them in my program that generates kay pairs to reject any pair that does not satisfy this list of requirments.

How to convert seeds into private key?

how to convert bip39 mnemonic seed phrase into private key without any libraries like web3 or ethers.js
basically I'm trying to replicate my metamasks wallets private key
so I would like to write a function that takes my seed words as my input and return the private key for ethereum based wallets
privateKey = function([seed_1, seed_2, ..., seed_12]);
Where do I get started?
#elangovan you can use dart's BIP32 implementation and follow below steps
Convert Mnemonic(12 words) to seed using bip32.mnemonicToSeed
Seedto HD Master Node using bip32.BIP32.fromSeed
Derive child node at desired HD path(m/44'/0')
However, you can derive public and private keys from the child node.

How to do SSL public key pinning in flutter/dart?

relatively new to Flutter here (and programming in general). Only familiar with the more basic stuffs but I've now encountered the need to use a CertificatePinner such as this in flutter/dart:
https://square.github.io/okhttp/3.x/okhttp/okhttp3/CertificatePinner.html (I've successfully implemented this in my previous kotlin/java project in android studio). My goal is to pin public key (not certificate)
All I have is the public key in the form of a string like shown below, nothing else:
"sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
How do I go about achieving this? I've asked this in an open issue on github but haven't gotten any responses yet (https://github.com/dart-lang/sdk/issues/35981). Hoping someone has managed to achieve this.
I've also scoured through other sources. I think the closest one to a solution for me is How can I do public key pinning in Flutter?
but I don't quite get what is being done there and I can't comment to ask questions there since I don't have enough reputation yet.
For comparison, all I want to do is achieve the same thing in flutter/dart what I could in java/kotlin with these few lines of code:
String hostname = "publicobject.com";
CertificatePinner certificatePinner = new CertificatePinner.Builder()
.add(hostname, "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
.build();
Thanks for your help
Start with the code in the answer you refer to. That takes the certificate in DER format and starts decoding it.
ASN1Parser p = ASN1Parser(der);
ASN1Sequence signedCert = p.nextObject() as ASN1Sequence;
ASN1Sequence cert = signedCert.elements[0] as ASN1Sequence;
ASN1Sequence pubKeyElement = cert.elements[6] as ASN1Sequence;
// this is the Subject Public Key element, which describes the type of key and actual value
For example, if we decode the certificate of pub.dev we find that it's an RSA key with a modulus of 65537 and a value of 2347......:
SEQUENCE (2 elem)
SEQUENCE (2 elem)
OBJECT IDENTIFIER 1.2.840.113549.1.1.1 rsaEncryption (PKCS #1)
NULL
BIT STRING (1 elem)
SEQUENCE (2 elem)
INTEGER (2048 bit) 234782553149463204049153749736864715384123240676730175743244004248041…
INTEGER 65537
From the RFC, the SPKI fingerprint is the SHA-256 hash of this whole element.
// you need to import dart:convert and package:crypto/crypto.dart
var hash = base64.encode(sha256.convert(pubKeyElement.contentBytes()).bytes);
var spkiFingerprint = 'sha256/$hash'; // should match the value you have
Caveats
The badCertificateCallback doesn't deliver the whole certificate chain, so you can't walk up the whole chain. What's worse is that it doesn't always seem to deliver the leaf certificate! Sometimes it delivers an intermediate certificate.

Saving/Reading BigInteger RSA keys to/from file

I am trying to implement RSA using Big integers i can currently encrypt and decrypt fine but I need to be able to take the 2 lots of 2 BigIntegers n, e and n, d of any Bit length up to 2048 and then some how save them to files named publicKey.txt and privateKey.txt . and then be able to read it in later. does anyone have any ideas for this.
would like to somehow save them like this so i can separate them into their 2 parts on reading them in using the , as the separator
publicKey.txt
n,e
privateKey.txt
n,d
RSA standard defines ASN.1 encoding for serializing private and public keys for transferring and storage. This format is a standard for cryptography software.

How to calculate a 256-bit HMAC_SHA3 hash with CryptoJS?

Recent CryptoJS versions support SHA3 hashing.
SHA3 can output different hash sizes, including 512-bit (default) and 256-bit. These two work fine:
var sha3_512_hash = CryptoJS.SHA3( 'test' );
var sha3_256_hash = CryptoJS.SHA3( 'test' , { outputLength:256 } );
Similarly, CryptoJS can also calculate HMAC values. However, I can't figure out how to change the default output size there:
var sha3_512_hmac = CryptoJS.HmacSHA3( 'test' , 'key' );
var sha3_256_hmac = CryptoJS.HmacSHA3( 'test' , 'key' , { outputLength:256 } );
The first works OK (the result is a 512-bit hmac value) but the second is the same (i.e. also 512-bit), as if it ignores the {outputLength:256} parameter!
Here's a live example: http://jsfiddle.net/M8xf3/ (using hmac-sha3.js from CryptoJS 3.1.2)
Does anyone know how to create 256-bit SHA3-based HMAC hashes?
P.S. For the SHA2 family of functions, CryptoJS has separate Hmac functions for each output size (that's HmacSHA256 and HmacSHA512). But this doesn't seem to be the case for SHA3?
This doesn't answer the actual question, but note that with SHA3 you don't really need HMAC hashes. Unlike SHA1 and SHA2 and MD5, SHA3 is not vulnerable to length-extension attacks.
Therefore with SHA3 it would suffice to just prepend or append the secret key to your input.
Or, if you're paranoid of a single hash step becoming compromised (not to be expected in the foreseeable future, especially not with SHA3, but still) you could do something like SHA3(key+SHA3(key+data)) or SHA3(key+SHA3(key+data)+data) (obviously with "+" denoting binary concatenation).
You can just edit hmac-sha3.js and change the outputLength to 256-bit instead of 512-bit.
Open hmac-sha3.js file, using your text editor.
Find "{outputLength:512}" and replace it with "{outputLength:256}"
Then the hash output will be 256-bit in length.
To be sure that you did not messed up things, double check your 256-bit hmac-sha3 output with some test cases available on the internet, for example: http://www.di-mgt.com.au/hmac_sha3_testvectors.html