McEliece (Bouncy Castle) Getting the public key back - java

I am currently trying to implement McEliece encryption using BC but running into some trouble. I currently have the capabilities to create the keys and place them into a file, i can read them back into the program but cannot get it to go from bytes back to Public Key.
Below is what i currently have:
public static String EncryptText(Component tmp, String Plaintext) throws InvalidKeyException, InvalidCipherTextException {
String CipherText = "Didnt Work";
try {
// The message to encrypt.
byte[] messageBytes = Plaintext.getBytes();
//read in the Public Key to use to Encrypt.
File f = new File(tmp.getPublicKey());
FileInputStream fis = new FileInputStream(f);
byte[] PubKeybytes = new byte[fis.available()];
fis.read(PubKeybytes);
fis.close();
//turn the bytes into the Key.
X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(PubKeybytes);
SubjectPublicKeyInfo PKI ;
KeyFactory KF = null;
try {
KF = KeyFactory.getInstance("McEliece");
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(McEliecePKCS.class.getName()).log(Level.SEVERE, null, ex);
}
PublicKey PK = null;
try {
PK = KF.generatePublic(pubKeySpec);
} catch (InvalidKeySpecException ex) {
Logger.getLogger(McEliecePKCS.class.getName()).log(Level.SEVERE, null, ex);
}
//Public Key
PublicKey aPublic = PK;
McEliecePublicKeyParameters GPKP = (McEliecePublicKeyParameters) McElieceKeysToParams.generatePublicKeyParameter(aPublic);
//set the public key to use.
McElieceCipher EnCipheredText = new McElieceCipher();
EnCipheredText.init(true, GPKP);
EnCipheredText.initCipherEncrypt(GPKP);
byte[] ciphertextBytes;
//sign the message with the public key.
ciphertextBytes = EnCipheredText.messageEncrypt(messageBytes);
CipherText = new String(ciphertextBytes);
return CipherText;
} catch (IOException ex) {
Logger.getLogger(McEliecePKCS.class.getName()).log(Level.SEVERE, null, ex);
}
return CipherText;
}\
The current error im having with this code is with the KeyFactory and that "McEliece" is not considered an algorithm as im getting NoSuchAlgorithmException but im not really sure what else to try at the moment. i have also tried to use the KeyFactory that is included with BouncyCastle for McEliece but had no success as the methods were either protected or did not allow for KeySpec and wanted SubjectPublicKeyInfo which i could not figure out how to change the KeySpec into or the Byte array into.
Sorry if this is a simple question im fairly new to coding Cryptography.
Thanks for the replies in advance.

Managed to figure out the issue. i needed to add:
Security.addProvider(new BouncyCastleProvider());
Security.addProvider(new BouncyCastlePQCProvider());

Related

java.security.InvalidKeyException when implementing DH protocol

In my android application I would like to implement the Diffie-Hellman protocol in order to generate a common secret between two users.
What I do is the following: when the first user sends a friendship request to the second one, the app generates a key pair, storing the public one in a remote database and the private in a local database.
Here is the code for this first part:
generateKeys();
localDB.insertPrivateKey(userId, entityId, privateKey);
remoteDB.insertFirstPublicKey(userId, entityId, publicKey);
The generateKeys method is the following:
private void generateKeys() {
try {
final KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DH");
keyPairGenerator.initialize(1024);
final KeyPair keyPair = keyPairGenerator.generateKeyPair();
privateKey = keyPair.getPrivate();
publicKey = keyPair.getPublic();
} catch (Exception e) {
e.printStackTrace();
}
}
When the second user accepts the request, another key pair is generated, once again storing the private key in the local db and the public in the remote. Then it fetches the public key of the first user from the remote db, converts it back to PublicKey and generate the common secret.
Here is the code for the second part:
generateKeys();
localDB.insertPrivateKey(userId, entityId, privateKey);
remoteDB.insertSecondPublicKey(entityId, userId, publicKey);
String stringFirstPubKey = remoteDB.fetchFirstKey(entityId, userId);
PublicKey firstPubKey = stringToPublicKey(stringFirstPubKey);
byte[] commonSecret = generateCommonSecret(firstPubKey);
The stringToPublicKey is the following:
private PublicKey stringToPublicKey(String stringPubK) throws NoSuchAlgorithmException, InvalidKeySpecException {
byte[] pubK = Base64.decodeBase64(stringPubK);
KeyFactory keyFactory = KeyFactory.getInstance("DH");
EncodedKeySpec keySpec = new X509EncodedKeySpec(pubK);
return keyFactory.generatePublic(keySpec);
}
And the generataCommonSecret:
private byte[] generateCommonSecret(PublicKey firstPubKey) {
try {
final KeyAgreement keyAgreement = KeyAgreement.getInstance("DH");
keyAgreement.init(privateKey);
keyAgreement.doPhase(firstPubKey, true);
byte[] secretKey = adjustKeyLenght(keyAgreement.generateSecret());
return secretKey;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
Also when storing the keys I convert them into String with the following:
String stringPubK = Base64.encodeBase64String(publicKey.getEncoded());
When executing the following line in generateCommonSecret
keyAgreement.doPhase(firstPubKey, true);
I get this exception
java.security.InvalidKeyException: DHPublicKey not for this KeyAgreement!
at com.android.org.bouncycastle.jcajce.provider.asymmetric.dh.KeyAgreementSpi.engineDoPhase(KeyAgreementSpi.java:101)
at javax.crypto.KeyAgreement.doPhase(KeyAgreement.java:383)
Can someone help me finding the problem? What is weird is that if I try to do this in a single java class, without storing and retrieving keys, it works fine.

RSA Encryption Error

I have generated a public and private code with puttygen, the private key is exported as openssl, the name of the peys are public_key.der , private_key.pem but when i try to use java to encrypt it i get this error:
java.io.FileNotFoundException: public_key.der
The codode is :
public static String RSAPublicEncryptuion(String text){
DataInputStream dis = null;
try {
File pubKeyFile = new File("public_key.der");
dis = new DataInputStream(new FileInputStream(pubKeyFile));
byte[] keyBytes = new byte[(int) pubKeyFile.length()];
dis.readFully(keyBytes);
dis.close();
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
RSAPublicKey publicKey = (RSAPublicKey)keyFactory.generatePublic(keySpec);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
String textoEncryptado = new String(cipher.doFinal(text.getBytes()), "UTF-8");
return textoEncryptado;
} catch (FileNotFoundException ex) {
Logger.getLogger(RSAEncrypt.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException | NoSuchAlgorithmException | InvalidKeySpecException | NoSuchPaddingException | InvalidKeyException ex) {
Logger.getLogger(RSAEncrypt.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalBlockSizeException | BadPaddingException ex) {
Logger.getLogger(RSAEncrypt.class.getName()).log(Level.SEVERE, null, ex);
}
return "Error";
}
The public_key are in the same package than this class (testras.ras), what i'm doing wrong ?
Thanks for all!
Sorry for my bad English
Your current approach (using a relative filepath) depends on the location of the key file relative to the working directory at runtime, which can be non-obvious.
However, you mention that the public key file is "in the same place where the .class" file is -- you can leverage this fact to gain a more flexible solution. Try using Class.getResourceAsStream, as illustrated below:
InputStream is = RSAEncrypt.class.getResourceAsStream("public_key.der");

How to Encrypt and Decrypt file Using RSA And AES Algorithm [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I want to encrypt test.txt file I am using this java class for encryption and decryption.In My directory I have three files private.txt for save private key and public.txt for public key and test.txt is for encryption.
package EncryptionDecryption;
import java.io.BufferedInputStream;
public class EncryptionUtil {
/**
* String to hold name of the encryption algorithm.
*/
public static final String ALGORITHM = "RSA";
/**
* String to hold the name of the private key file.
*/
public static final String PRIVATE_KEY_FILE = "private.txt";
/**
* String to hold name of the public key file.
*/
public static final String PUBLIC_KEY_FILE = "public.txt";
public static void generateKey() {
try {
final KeyPairGenerator keyGen = KeyPairGenerator.getInstance(ALGORITHM);
keyGen.initialize(1024);
final KeyPair key = keyGen.generateKeyPair();
File privateKeyFile = new File(PRIVATE_KEY_FILE);
File publicKeyFile = new File(PUBLIC_KEY_FILE);
// Create files to store public and private key
if (privateKeyFile.getParentFile() != null) {
privateKeyFile.getParentFile().mkdirs();
}
privateKeyFile.createNewFile();
if (publicKeyFile.getParentFile() != null) {
publicKeyFile.getParentFile().mkdirs();
}
publicKeyFile.createNewFile();
// Saving the Public key in a file
ObjectOutputStream publicKeyOS = new ObjectOutputStream(
new FileOutputStream(publicKeyFile));
publicKeyOS.writeObject(key.getPublic());
System.out.println("public"+key.getPublic().getEncoded());
publicKeyOS.close();
// Saving the Private key in a file
ObjectOutputStream privateKeyOS = new ObjectOutputStream(
new FileOutputStream(privateKeyFile));
privateKeyOS.writeObject(key.getPrivate());
System.out.println("private"+key.getPrivate().getEncoded());
//System.out.println(key.getPrivate());
privateKeyOS.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static boolean areKeysPresent() {
File privateKey = new File(PRIVATE_KEY_FILE);
File publicKey = new File(PUBLIC_KEY_FILE);
if (privateKey.exists() && publicKey.exists()) {
return true;
}
return false;
}
public static byte[] encrypt(byte[]bs, PublicKey key) {
byte[] cipherText = null;
try {
// get an RSA cipher object and print the provider
final Cipher cipher = Cipher.getInstance(ALGORITHM);
// encrypt the plain text using the public key
cipher.init(Cipher.ENCRYPT_MODE, key);
cipherText = cipher.doFinal(bs);
} catch (Exception e) {
e.printStackTrace();
}
return cipherText;
}
public static String decrypt(byte[] text, PrivateKey key) {
byte[] dectyptedText = null;
try {
// get an RSA cipher object and print the provider
final Cipher cipher = Cipher.getInstance(ALGORITHM);
// decrypt the text using the private key
cipher.init(Cipher.DECRYPT_MODE, key);
dectyptedText = cipher.doFinal(text);
} catch (Exception ex) {
ex.printStackTrace();
}
return new String(dectyptedText);
}
public static void main(String[] args)throws IOException {
System.out.println("Hai");
try {
// Check if the pair of keys are present else generate those.
generateKey();
File f=new File("test.txt");
byte[] contents = new byte[(int)f.length()];
BufferedInputStream bis = null;
try
{
bis = new BufferedInputStream(new FileInputStream(f));
DataInputStream dis = new DataInputStream(bis);
dis.readFully(contents);
}
finally
{
if(bis != null)
{
bis.close();
}
}
// final String originalText = "Text to be encrypted";
// Encrypt the string using the public key
ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(PUBLIC_KEY_FILE));
final PublicKey publicKey = (PublicKey) inputStream.readObject();
final byte[] cipherText = encrypt(contents, publicKey);
inputStream.close();
// Decrypt the cipher text using the private key.
ObjectInputStream inputStream1 = new ObjectInputStream(new FileInputStream(PRIVATE_KEY_FILE));
final PrivateKey privateKey = (PrivateKey) inputStream1.readObject();
final String plainText = decrypt(cipherText, privateKey);
// Printing the Original, Encrypted and Decrypted Text
System.out.println("Original Text: " + contents.toString());
System.out.println("Encrypted Text: " +cipherText);
System.out.println("Decrypted Text: " + plainText);
inputStream.close();
inputStream1.close();
} catch (Exception e) {
e.printStackTrace();
}
finally
{
}
}
}
I got this error when debugging
I
public[B#f73c1
private[B#15b9e68
javax.crypto.IllegalBlockSizeException: Data must not be longer than 117 bytes
at com.sun.crypto.provider.RSACipher.a(DashoA13*..)
at com.sun.crypto.provider.RSACipher.engineDoFinal(DashoA13*..)
at javax.crypto.Cipher.doFinal(DashoA13*..)
at EncryptionDecryption.EncryptionUtil.encrypt(EncryptionUtil.java:122)
at EncryptionDecryption.EncryptionUtil.main(EncryptionUtil.java:193)
java.lang.IllegalArgumentException: Null input buffer
at javax.crypto.Cipher.doFinal(DashoA13*..)
at EncryptionDecryption.EncryptionUtil.decrypt(EncryptionUtil.java:147)
at EncryptionDecryption.EncryptionUtil.main(EncryptionUtil.java:198)
java.lang.NullPointerException
at java.lang.String.<init>(String.java:593)
at EncryptionDecryption.EncryptionUtil.decrypt(EncryptionUtil.java:153)
at EncryptionDecryption.EncryptionUtil.main(EncryptionUtil.java:198)
There is a good basic example here on encrypting a String with. This example uses DES but I belive the principle is the same and so will hopefully help get you started.
The Stack Trace you have posted is very similar to the issue faced in this post. There is an accepted answer there if you have a look which may provide you with a fix also.
Good luck!

Decrypted string not the same as pre encrypted string

I have the following pieces of code:
Globals
public static PublicKey pubKey;
public static PrivateKey privKey;
public static Cipher cip;
Main
public static void main(String[] args) throws Exception {
//Generate the keys
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(1024);
KeyPair kp = kpg.genKeyPair();
Key publicKey = kp.getPublic();
Key privateKey = kp.getPrivate();
KeyFactory fact = KeyFactory.getInstance("RSA");
cip = Cipher.getInstance("RSA/ECB/NoPadding");
// Store Public Key.
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(
publicKey.getEncoded());
FileOutputStream fos = new FileOutputStream("public.key");
fos.write(x509EncodedKeySpec.getEncoded());
fos.close();
// Store Private Key.
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(
privateKey.getEncoded());
fos = new FileOutputStream("private.key");
fos.write(pkcs8EncodedKeySpec.getEncoded());
fos.close();
//Get the public and private keys out of their files
getPubAndPrivateKey();
//Check if the keys gotten out of the files are the same as the generated files (this returns truetrue)
System.out.print(publicKey.equals(pubKey));
System.out.print(privateKey.equals(privKey));
byte[] text = "This is my super secret secret".getBytes();
encryptToFile("encrypted.txt", text );
decryptToFile("encrypted.txt", "decrypted.txt");
}
Getting the keys from the files
private static void getPubAndPrivateKey() throws IOException, Exception {
// Read Public Key.
File filePublicKey = new File("public.key");
FileInputStream fis = new FileInputStream("public.key");
byte[] encodedPublicKey = new byte[(int) filePublicKey.length()];
fis.read(encodedPublicKey);
fis.close();
// Read Private Key.
File filePrivateKey = new File("private.key");
fis = new FileInputStream("private.key");
byte[] encodedPrivateKey = new byte[(int) filePrivateKey.length()];
fis.read(encodedPrivateKey);
fis.close();
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(
encodedPublicKey);
pubKey = keyFactory.generatePublic(publicKeySpec);
PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(
encodedPrivateKey);
privKey = keyFactory.generatePrivate(privateKeySpec);
}
Encrypting
public static void encryptToFile(String fileName, byte[] data)
throws IOException {
try {
cip.init(Cipher.ENCRYPT_MODE, privKey);
byte[] cipherData = cip.doFinal(data);
String encryptedData = cipherData.toString();
BufferedWriter out = new BufferedWriter(new FileWriter(fileName));
out.write(encryptedData);
out.close();
} catch (Exception e) {
throw new RuntimeException("Spurious serialisation error", e);
}
}
Decrypting
private static void decryptToFile(String string, String string2)
throws Exception {
try {
File encryptedFile = new File("encrypted.txt");
byte[] encrypted = getContents(encryptedFile).getBytes();
cip = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cip.init(Cipher.DECRYPT_MODE, pubKey);
byte[] cipherData = cip.doFinal(encrypted);
String decryptedData = cipherData.toString();
BufferedWriter out = new BufferedWriter(new FileWriter(
"decrypted.txt"));
out.write(decryptedData);
out.close();
} catch (Exception e) {
throw e;
}
}
Things I already checked
The data used in the decryption is the same as in the encrypted file
The generated keys are the same as the ones gotten from the file
The encryption and decryption both don't give errors
Results
Original string:
My super secret secret
The encryption results in:
[B#1747b17
The decryption results in:
[B#91a4fb
If you print out a byte array via toString() method you are getting a value that is totally independent of the content.
Therefore the values [B#1747b17 [B#91a4fb are just garbage that does not tell you anything.
If you want to print the content of a byte array convert it to Base64 or hex-string.
System.out.println(new sun.misc.BASE64Encoder().encode(myByteArray));
A hex string can be generated by using org.apache.commons.codec.binary.Hex from Apache Commons Codec library.
I agree with the above answer.
I would like to add that in your case, you can simply use FileOutputStream, write the bytes to a file -
For example:
public static void encryptToFile(String fileName, byte[] data)
throws IOException {
FileOutputStream out = null;
try {
cip.init(Cipher.ENCRYPT_MODE, privKey);
byte[] cipherData = cip.doFinal(data);
out = new FileOutputStream(fileName);
out.write(cipherData);
} catch (Exception e) {
throw new RuntimeException("Spurious serialisation error", e);
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException ex) {
}
}
}
}

How to encrypt decrypt with RSA keys in java

I need to replace the encrypt and decrypt step from Unix to java code with the rsaprivatekey.pem and rsapublickey.pem keys generated with openssl
I generate the keys
openssl genrsa -out /tmp/rsaprivatekey.pem -des3 1024
openssl rsa -in /tmp/rsaprivatekey.pem -pubout -out /tmp/rsapublickey.pem
i use the keys in unix (i need do it in java)
echo "Text to encript"| openssl rsautl -encrypt -inkey /tmp/rsapublickey.pem -pubin -out out.enc
openssl rsautl -decrypt -inkey /tmp/rsaprivatekey.pem -in out.enc
This was my attempt to do it
public static void main(String[] args) {
Base64 base64 = new Base64();
String TextStream = "this is the input text";
byte[] Cipher;
System.out.println("input:\n" + TextStream);
Cipher = encrypt(TextStream);
System.out.println("cipher:\n" + base64.encodeAsString(Cipher));
System.out.println("decrypt:\n" + decrypt(Cipher));
}
private static byte[] encrypt(String Buffer) {
try {
Cipher rsa;
rsa = Cipher.getInstance("RSA");
rsa.init(Cipher.ENCRYPT_MODE, getPrivateKey(PRIVATE_PATH));
return rsa.doFinal(Buffer.getBytes());
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static String decrypt(byte[] buffer) {
try {
Cipher rsa;
rsa = Cipher.getInstance("RSA");
rsa.init(Cipher.DECRYPT_MODE, getPrivateKey(PUBLIC_PATH));
byte[] utf8 = rsa.doFinal(buffer);
return new String(utf8, "UTF8");
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static PrivateKey getPrivateKey(String filename) throws Exception {
File f = new File(filename);
FileInputStream fis = new FileInputStream(f);
DataInputStream dis = new DataInputStream(fis);
byte[] keyBytes = new byte[(int) f.length()];
dis.readFully(keyBytes);
dis.close();
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePrivate(spec);
}
public static PublicKey getPublicKey(String filename) throws Exception {
File f = new File(filename);
FileInputStream fis = new FileInputStream(f);
DataInputStream dis = new DataInputStream(fis);
byte[] keyBytes = new byte[(int) f.length()];
dis.readFully(keyBytes);
dis.close();
X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePublic(spec);
}
but it not works, the PKCS8EncodedKeySpec/X509EncodedKeySpec are not correct... but i do not know what to put
Solution:
Thanks to #Sanjeev, using the bouncy castle API, I was able to encrypt/decrypt with the keys generated by openssl
public static void main(String[] args) throws IOException {
Security.addProvider(new BouncyCastleProvider());
KeyPair keyPair = readKeyPair(new File(PRIVATE_PATH), "pass");
// if the private key is not encripted, pass can be anything.
Key publickey = readPublicKey(new File(PUBLIC_PATH), "pass");
Base64 base64 = new Base64();
String text = "this is the input text";
byte[] encripted;
System.out.println("input:\n" + text);
encripted = encrypt(keyPair.getPublic(), text);
System.out.println("cipher:\n" + base64.encodeAsString(encripted));
System.out.println("decrypt:\n" + decrypt(keyPair.getPrivate(), encripted));
}
private static byte[] encrypt(Key pubkey, String text) {
try {
Cipher rsa;
rsa = Cipher.getInstance("RSA");
rsa.init(Cipher.ENCRYPT_MODE, pubkey);
return rsa.doFinal(text.getBytes());
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static String decrypt(Key decryptionKey, byte[] buffer) {
try {
Cipher rsa;
rsa = Cipher.getInstance("RSA");
rsa.init(Cipher.DECRYPT_MODE, decryptionKey);
byte[] utf8 = rsa.doFinal(buffer);
return new String(utf8, "UTF8");
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static KeyPair readKeyPair(File privateKey, String keyPassword) throws IOException {
FileReader fileReader = new FileReader(privateKey);
PEMReader r = new PEMReader(fileReader, new DefaultPasswordFinder(keyPassword.toCharArray()));
try {
return (KeyPair) r.readObject();
} catch (IOException ex) {
throw ex;
} finally {
r.close();
fileReader.close();
}
}
private static Key readPublicKey(File privateKey, String keyPassword) throws IOException {
FileReader fileReader = new FileReader(privateKey);
PEMReader r = new PEMReader(fileReader, new DefaultPasswordFinder(keyPassword.toCharArray()));
try {
return (RSAPublicKey) r.readObject();
} catch (IOException ex) {
throw ex;
} finally {
r.close();
fileReader.close();
}
}
I think you're having problems reading PEM files. The JPA doesn't directly support the PEM format. You have two options, either convert them to DER encoded files (you can use openSSL to do this) or the you can use the bouncy castle API to read (or write) PEM files. the class you'd be interested in is called PEMReader (and maybe also PEMWriter). Here is the Javadoc on the bouncycastle website.

Categories

Resources