How to create a key pair in Java based on a password?

I want Alice to create a pair of public / private keys so that Bob can send her private messages. However, I want Alice to be able to check her messages from anywhere, and it would be painful if she had to carry a memory stick with her secret key. Is there a way Alice can create a public / private key pair based on the password she remembers? That way, she could just generate a private key (and public key) whenever she wanted.

Short version of this question: Where can I find the Java equivalent of cryptico.js .

Also, here is the same stack overflow question , but for javascript.

Edit: Here is my first attempt at a solution:

SecureRandom saltRand = new SecureRandom(new byte[] { 1, 2, 3, 4 }); byte[] salt = new byte[16]; saltRand.nextBytes(salt); int keyLength = 3248; SecretKeyFactory factory = SecretKeyFactory .getInstance("PBKDF2WithHmacSHA1"); KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 8192, keyLength); SecretKey key = factory.generateSecret(spec); SecureRandom keyGenRand = SecureRandom.getInstance("SHA1PRNG"); keyGenRand.setSeed(key.getEncoded()); KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA"); gen.initialize(keyLength, keyGenRand); java.security.KeyPair p = gen.generateKeyPair(); 
+6
source share
5 answers

When talking to RSA: you can use the PBKDF2 result to seed a pseudo-random number generator, which in turn can be used to create a key pair. Please note that using SecureRandom will not work, as it will add seed to the pool instead of fully reinitializing rng. RSA needs PRNG to search for a random prime.

You are better off if you can use cryptography with an elliptic curve. You can choose a standard NIST or Brainpool curve over F (p). You can then use the output of 32 bytes PBKDF2 as the private key and calculate the public key. ECC requires only a random private key, and since the output of PBKDF2 must be indistinguishable from random, the output will be perfect. Not only do you need additional PRNG, you can also spend your time calculating the RSA key pair yourself, and this can be significant.

Please note that nothing will prevent a brute force attack on something encrypted with the specified calculated key, so you are better off asking for a code phrase of 16 characters or more containing word words, numbers and signs. Anything less likely to fail, especially if users are not aware of possible attacks. Please note: if you do not have storage, you cannot use random salt. Unless you have a random salt that you cannot protect from rainbow tables (for your specific application, you can, of course, use the salt of the application). In addition, individuals with the same phrase will generate the same secret key.

Of course, the default method — for example, in PGP — is to store a secret key that is encrypted using password-based encryption. However, this requires storage. The advantage of this approach is that you can have a completely random key, which means that rude attacks against encrypted texts are impossible without access to the keystore. It adds an important extra layer.

+5
source

You do not provide much detail, but if you want to generate your key pair using java.security.KeyPairGenerator , you will need to define your own class that extends SecureRandom , but uses only the provided password as the source of entropy.

You do not need to implement the SecureRandomSpi class, you can just call the protected constructor of the superclass with arguments (null, null) .

+3
source

The RSA key length is typically 1024 or 2048 bits. This is 128 or 256 bytes.

Passwords usually have a length of 8 bytes (and use only about 64 different bytes).

You will lose most of the algorithm if the RSA key was obtained from the password. An attacker would only guess or roughly force an 8-byte password instead of a 128 or 256-byte key.

+1
source

Why don't you allow access to your web application with a password (since this is what you do effectively) and just use https?

0
source

use a shared key.

 String encryptionKey = "53616d706c6550617373776f726453616d706c6550617373776f726453616d70"; // string to hex of "SamplePasswordSamplePasswordSamp" String sampleText = "sampletext"; String encrypted = null; String decrypted = null; 

Encrypt Usage:

 Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(Hex.decodeHex(encryptionKey.toCharArray()), "AES")); encrypted = Hex.encodeHexString(cipher.doFinal((sampleText.toString()).getBytes())); 

To decrypt usage:

  Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(Hex.decodeHex(encryptionKey.toCharArray()), "AES")); decrypted = new String(cipher.doFinal(Hex.decodeHex(enc.toCharArray()))); 

Hex note : import org.apache.commons.codec.binary.Hex; in maven:

 <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>1.6</version> </dependency> 
0
source

Source: https://habr.com/ru/post/921070/


All Articles