How to encrypt an object in Azure using KeyVaultClient (JAVA) - java

Normally encryption happens for byte Arrays plainText.
promise = keyVaultClient.encryptAsync(keyId.getBaseIdentifier(), JsonWebKeyEncryptionAlgorithm.RSAOAEP, plainText);
result = promise.get();
cipherText = result.getResult();
Where KeyVaultClient object encrypt byte[] and returns Future.
How to encrypt an object?

You can see soucre code of encryptAsync method as below in azure keyvault java sdk:
public ServiceFuture<KeyOperationResult> encryptAsync(String keyIdentifier, JsonWebKeyEncryptionAlgorithm algorithm, byte[] value, final ServiceCallback<KeyOperationResult> serviceCallback) {
KeyIdentifier id = new KeyIdentifier(keyIdentifier);
return innerKeyVaultClient.encryptAsync(id.vault, id.name, id.version == null ? "" : id.version, algorithm, value, serviceCallback);
}
Observe the parameters required in this method, and it's not difficult to find that it needs the parameters of the byte[] type, so you just have to convert object to byte[].
You can refer to the code which mentioned in the SO thread:Java Serializable Object to Byte Array.
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutput out = null;
try {
out = new ObjectOutputStream(bos);
out.writeObject(yourObject);
out.flush();
byte[] yourBytes = bos.toByteArray();
...
} finally {
try {
bos.close();
} catch (IOException ex) {
// ignore close exception
}
}

Related

How to encrypt Credentials object - Cipher.doFinal, SealedObject, or CipherOutputStream?

I need to encrypt a set of user credentials and send it to a SOAP web service. The following code snippet (I think it's C#) is provided in the documentation, and my Java code is based on it.
private string Encrypt256(string text, AesCryptoServiceProvider aes)
{
// Convert string to byte array
byte[] src = Encoding.Unicode.GetBytes(text);
// encryption
using (ICryptoTransform encrypt = aes.CreateEncryptor())
{
byte[] dest = encrypt.TransformFinalBlock(src, 0, src.Length);
// Convert byte array to Base64 strings
return Convert.ToBase64String(dest);
}
}
...
Credentials credential = new Credentials();
credential.UserName = "username";
credential.Password = "password";
credential.ClientUtcTime = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ", System.Globalization.CultureInfo.InvariantCulture);
//--Serialize credential
XmlSerializer serializer = new XmlSerializer(credential.GetType());
string xmlCredential = string.Empty;
using (var stringwriter = new System.IO.StringWriter())
{
serializer.Serialize(stringwriter, credential);
xmlCredential = stringwriter.ToString();
}
//--Encrypt credential with AES256 symmetric
String encryptedCredential = Encrypt256(xmlCredential, aesServiceProvider);
...
The following is my Java code.
KeyGenerator kg = KeyGenerator.getInstance("AES");
kg.init(256);
SecretKey sk = kg.generateKey();
Cipher aesCipher = Cipher.getInstance("AES");
aesCipher.init(Cipher.ENCRYPT_MODE, sk);
Credentials cred = new UsernamePasswordCredentials("username", "password");//no need for time field?
String eCred = Base64.encodeBase64String(aesCipher.doFinal(objectToByteArray(cred)));
...
private byte[] objectToByteArray(Object obj) {
byte[] bytes = null;
try (
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
) {
oos.writeObject(obj);
oos.flush();
bytes = bos.toByteArray();
}
catch (IOException e) {
e.printStackTrace();
}
return bytes;
}
Then I came across SealedObject and CipherOutputStream. I tried writing code snippets for those.
Using SealedObject
// slight change here; cred must implement Serializable
UsernamePasswordCredentials cred = new UsernamePasswordCredentials("username", "password");
// same as above except for the following two lines
SealedObject so = new SealedObject(cred, aesCipher);
String eCred = Base64.encodeBase64String(objectToByteArray(so));
Using CipherOutputStream
Credentials cred = new UsernamePasswordCredentials("username", "password");
ByteArrayOutputStream bos = new ByteArrayOutputStream();
CipherOutputStream cos = new CipherOutputStream(bos, aesCipher);
cos.write(objectToByteArray(cred));
cos.close();
String eCred = Base64.encodeBase64String(bos.toByteArray());
For all three code snippets, is the code correct? Considering that this code will be called frequently, which approach is the most efficient?

java read encrypted Objects

Hello I have following Problem:
I have an Class/Object Access wich is Serializable.
public class Access implements Serializable {
private static final long serialVersionUID = 1L;
private URL website;
private String username;
private String password;
// + some methods
}
Now when writing them to a File i encrypt them using a Cipher. Looks like this:
WRITING:
ObservableList<Access> userData;
userData = FXCollections.observableArrayList();
...
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, key128);
File file = new File("./resources/saves" + username);
file.createNewFile();
CipherOutputStream cipherOut = new CipherOutputStream(
new BufferedOutputStream(new FileOutputStream(file, true)), cipher);
ObjectOutputStream out = new ObjectOutputStream(cipherOut);
userData.forEach((item) -> {
try {
out.writeObject(new SealedObject(item, cipher));
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
});
out.flush();
out.close();
READING:
ObservableList<Access> access = FXCollections.observableArrayList();
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, key128);
CipherInputStream cipherIn = new CipherInputStream(
new BufferedInputStream(new FileInputStream("./resources/saves" + username)), cipher);
ObjectInputStream in = new ObjectInputStream(cipherIn);
SealedObject sealed;
while ((sealed = (SealedObject) in.readObject()) != null) {
access.add((Access) sealed.getObject(cipher));
}
If i now Load the File it seems corrupted. I find it hard to find the mistake. I think the Problem is in the load function. Am i missing something obvious here?
Error:
java.io.StreamCorruptedException: invalid stream header: 3D23898C
Thank you for your time & help! :*
Okay, The problem is the interaction between the cipher stream and the object stream.
When you read the file, the ObjectInputStream asks to the underlying stream (the cipher stream) to read a very specific header. But the cipher stream has zero knowledge of that - he reads the normal amount of bytes he is supposed to, according his own protocol, in order to make sense of the encrypted data. The result is that the ObjectInputStream gets a truncated/altered header and can't process the stream correctly.
Good news is, you don't actually need it ! The SealedObject will take care of encryption/decryption for you. Simply remove the cipher stream and it should work.
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file, true));
and to read:
FileInputStream inputStream = new FileInputStream(fileName);
ObjectInputStream ois = new ObjectInputStream(inputStream);
Now, if you really want to use the cipher stream (and thus effectively encrypt/decrypt the data twice with the same key), you need first to make a "first pass" on the file to decrypt it, and then open an object stream on the new decrypted file.
Did you forget to call out.flush() and out.close() ?
If you did, some data may not be actually be written to the disk and it'll be impossible to read it again.

how to decrypt in java (snippet of my code included)

I am wanting to create a functional Java chat application.
So I have a small application which allows users to connect via server classes and talk with each other via client classes and I have started to add Encryption. I am having trouble decrypting output from other clients in my Java chat application.
can someone help me please?
snippet of my code is included below:
THE CLIENTGUI.JAVA CLASS (encrypt is a button which is clicked)
if(o == encrypt) {
String change = null;
try{
change = tf.getText();
change = FileEncryption.encryptString(change);
tf.setText("" + change);
return;
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
finally{
}
THE FILEENCRYPTION.JAVA
public class FileEncryption {
//Initial Vector
public static final byte[] iv = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
//EncryptAndDecrypt String -> Input : PlainText + Return : CipherText+DecipherText
public static String encryptString(String src) throws Exception
{
String dst="";
//Not Input!
if(src == null || src.length()==0)
return "";
//Encryption Setting
byte[] k="Multimediaproces".getBytes();
SecretKeySpec Key = new SecretKeySpec(k,"AES");
IvParameterSpec ivspec = new IvParameterSpec(iv);
Cipher encryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
encryptCipher.init(Cipher.ENCRYPT_MODE,Key,ivspec);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
CipherOutputStream cout = new CipherOutputStream(baos,encryptCipher);
cout.write(src.getBytes());
cout.flush(); //ByteOutputStream -> Write Encryption Text
cout.close();
// in encrypt method
dst = DatatypeConverter.printHexBinary(baos.toByteArray());
return dst;
}
//String src -> EncryptedData
public static String decryptString(String src) throws Exception
{
//src value is Encrypted Value!
//So, src value -> Not Byte!
String dst="";
byte[] encryptedBytes = DatatypeConverter.parseHexBinary(src);;
//Not Input!
if(src == null || src.length()==0)
return "";
//Decryption Setting
IvParameterSpec ivspec = new IvParameterSpec(iv);
byte[] k="Multimediaproces".getBytes();
SecretKeySpec Key = new SecretKeySpec(k,"AES");
Cipher decryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
decryptCipher.init(Cipher.DECRYPT_MODE,Key,ivspec);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ByteArrayInputStream bais = new ByteArrayInputStream(encryptedBytes);
CipherInputStream cin = new CipherInputStream(bais,decryptCipher);
byte[] buf = new byte[1024];
int read;
while((read=cin.read(buf))>=0) //reading encrypted data!
{
baos.write(buf,0,read); //writing decrypted data!
}
// closing streams
cin.close();
dst = new String(baos.toByteArray());
return dst;
}
}
the problem is that when i try to decrypt the code entering the following code:
if(o == decrypt) {
try{
msg = tf.getText();
msg = FileEncryption.decryptString(msg);
fop.
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}finally{
}
Currently, it ALLOWS me to encrypt what I type into text field.
It does not allow me to decrypt the output of what the users have said in the chat. The current code I have included for the decrypt does not function.
Can anyone help me? or have any suggestions that I could make to my program to help it decrypt?
Thanks
EDIT:
Your best bet would probably be to simply use SSL sockets for your network communications, rather than writing the encryption code yourself. While your question isn't exactly a duplicate of this one, you'd likely be well served by the answers here:
Secret Key SSL Socket connections in Java
I suspect that the problem is not passing the encrypted status between the 2 clients.
If the "encrypt" object is a button then it is a button on only one side of the client-client connection. You will need to pass the encrypted state to the other client, so that it knows to decrypt the message.
A short cut to confirming this would be to automatically show the plaintext and decrypted message on the receiving end. One of them will always be gibberish but it should change depending on the use of the encrypt button.
Good luck :)

Java - Missing final characters when encrypting using blowfish

I am using some java code that encrypts the contents of a text file using Blowfish. When I convert the encrypted file back (i.e. decrypt it) the string is missing a character from the end. Any ideas why? I am very new to Java and have been fiddling with this for hours with no luck.
The file war_and_peace.txt just contains the string "This is some text". decrypted.txt contains "This is some tex" (with no t on the end). Here is the java code:
public static void encrypt(String key, InputStream is, OutputStream os) throws Throwable {
encryptOrDecrypt(key, Cipher.ENCRYPT_MODE, is, os);
}
public static void decrypt(String key, InputStream is, OutputStream os) throws Throwable {
encryptOrDecrypt(key, Cipher.DECRYPT_MODE, is, os);
}
private static byte[] getBytes(String toGet)
{
try
{
byte[] retVal = new byte[toGet.length()];
for (int i = 0; i < toGet.length(); i++)
{
char anychar = toGet.charAt(i);
retVal[i] = (byte)anychar;
}
return retVal;
}catch(Exception e)
{
String errorMsg = "ERROR: getBytes :" + e;
return null;
}
}
public static void encryptOrDecrypt(String key, int mode, InputStream is, OutputStream os) throws Throwable {
String iv = "12345678";
byte[] IVBytes = getBytes(iv);
IvParameterSpec IV = new IvParameterSpec(IVBytes);
byte[] KeyData = key.getBytes();
SecretKeySpec blowKey = new SecretKeySpec(KeyData, "Blowfish");
//Cipher cipher = Cipher.getInstance("Blowfish/CBC/PKCS5Padding");
Cipher cipher = Cipher.getInstance("Blowfish/CBC/NoPadding");
if (mode == Cipher.ENCRYPT_MODE) {
cipher.init(Cipher.ENCRYPT_MODE, blowKey, IV);
CipherInputStream cis = new CipherInputStream(is, cipher);
doCopy(cis, os);
} else if (mode == Cipher.DECRYPT_MODE) {
cipher.init(Cipher.DECRYPT_MODE, blowKey, IV);
CipherOutputStream cos = new CipherOutputStream(os, cipher);
doCopy(is, cos);
}
}
public static void doCopy(InputStream is, OutputStream os) throws IOException {
byte[] bytes = new byte[4096];
//byte[] bytes = new byte[64];
int numBytes;
while ((numBytes = is.read(bytes)) != -1) {
os.write(bytes, 0, numBytes);
}
os.flush();
os.close();
is.close();
}
public static void main(String[] args) {
//Encrypt the reports
try {
String key = "squirrel123";
FileInputStream fis = new FileInputStream("war_and_peace.txt");
FileOutputStream fos = new FileOutputStream("encrypted.txt");
encrypt(key, fis, fos);
FileInputStream fis2 = new FileInputStream("encrypted.txt");
FileOutputStream fos2 = new FileOutputStream("decrypted.txt");
decrypt(key, fis2, fos2);
} catch (Throwable e) {
e.printStackTrace();
}
}
`
There is a couple of things not optimal here.
But let's first solve your problem. The reason why the last portion of your input is somehow missing is the padding you specify: none! Without specifying a padding, the Cipher can just operate on full-length blocks (8 bytes for Blowfish). Excess input that is less than a block long will be silently discarded, and there's your missing text. In detail: "This is some text" is 17 bytes long, so two full blocks will be decrypted, and the final 17th byte, "t", will be discarded.
Always use a padding in combination with symmetric block ciphers, PKCS5Padding is fine.
Next, when operating with Cipher, you don't need to implement your own getBytes() - there's String#getBytes already doing the job for you. Just be sure to operate on the same character encoding when getting the bytes and when reconstructing a String from bytes later on, it's a common source of errors.
You should have a look at the JCE docs, they will help you avoiding some of the common mistakes.
For example, using String keys directly is a no-go for symmetric cryptography, they do not contain enough entropy, which would make it easier to brute-force such a key. The JCE gives you theKeyGenerator class and you should always use it unless you know exactly what you are doing. It generates a securely random key of the appropriate size for you, but in addition, and that is something people tend to forget, it will also ensure that it doesn't create a weak key. For example, there are known weak keys for Blowfish that should be avoided in practical use.
Finally, you shouldn't use a deterministic IV when doing CBC encryption. There are some recent attacks that make it possible to exploit this, resulting in total recovery of the message, and that's obviously not cool. The IV should always be chosen at random (using a SecureRandom) in order to make it unpredictable. Cipher does this for you by default, you can simply obtain the used IV after encryption with Cipher#getIV.
On another note, less security-relevant: you should close streams in a finally block to ensure they're closed at all cost - otherwise you will be left with an open file handle in case of an exception.
Here's an updated version of your code that takes all these aspects into account (had to use Strings instead of files in main, but you can simply replace it with what you had there):
private static final String ALGORITHM = "Blowfish/CBC/PKCS5Padding";
/* now returns the IV that was used */
private static byte[] encrypt(SecretKey key,
InputStream is,
OutputStream os) {
try {
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, key);
CipherInputStream cis = new CipherInputStream(is, cipher);
doCopy(cis, os);
return cipher.getIV();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
private static void decrypt(SecretKey key,
byte[] iv,
InputStream is,
OutputStream os)
{
try {
Cipher cipher = Cipher.getInstance(ALGORITHM);
IvParameterSpec ivSpec = new IvParameterSpec(iv);
cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
CipherInputStream cis = new CipherInputStream(is, cipher);
doCopy(cis, os);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
private static void doCopy(InputStream is, OutputStream os)
throws IOException {
try {
byte[] bytes = new byte[4096];
int numBytes;
while ((numBytes = is.read(bytes)) != -1) {
os.write(bytes, 0, numBytes);
}
} finally {
is.close();
os.close();
}
}
public static void main(String[] args) {
try {
String plain = "I am very secret. Help!";
KeyGenerator keyGen = KeyGenerator.getInstance("Blowfish");
SecretKey key = keyGen.generateKey();
byte[] iv;
InputStream in = new ByteArrayInputStream(plain.getBytes("UTF-8"));
ByteArrayOutputStream out = new ByteArrayOutputStream();
iv = encrypt(key, in, out);
in = new ByteArrayInputStream(out.toByteArray());
out = new ByteArrayOutputStream();
decrypt(key, iv, in, out);
String result = new String(out.toByteArray(), "UTF-8");
System.out.println(result);
System.out.println(plain.equals(result)); // => true
} catch (Exception e) {
e.printStackTrace();
}
}
You have your CipherInputStream and CipherOutputStream mixed up. To encrypt, you read from a plain inputstream and write to a CipherOutputStream. To decrypt ... you get the idea.
EDIT:
What is happening is that you have specified NOPADDING and you are attempting to encrypt using a CipherInputStream. The first 16 bytes form two valid complete blocks and so are encrypted correctly. Then there is only 1 byte left over, and when the CipherInputStream class receives the end-of-file indication it performs a Cipher.doFinal() on the cipher object and receives an IllegalBlockSizeException. This exception is swallowed, and read returns -1 indicating end-of-file. If however you use PKCS5PADDING everything should work.
EDIT 2:
emboss is correct in that the real issue is simply that it is tricky and error-prone to use the CipherStream classes with the NOPADDING option. In fact, these classes explicitly state that they silently swallow every Security exception thrown by the underlying Cipher instance, so they are perhaps not a good choice for beginners.
Keys are binary, and String is not a container for binary data. Use a byte[].
When I had this problem I had to call doFinal on the cipher:
http://docs.oracle.com/javase/1.4.2/docs/api/javax/crypto/Cipher.html#doFinal()

Encrypting and decrypting xml [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I am making an app in which I have to encrypt the xml from my side and send it to server and in response I will receive xml and I have to decrypt it. I have no idea to encrypt and decrypt. My code is as follows
<?xml version='1.0' encoding='utf-8'?><adm_auth_req><user_name>user.s7</user_name><password>gspcsmo</password></adm_auth_req>
I am using this code to encrypt and decrypt it
public string encryptData(string key, string data)
{
int keyLen = key.Length;
int dataLen = Convert.ToInt16(data.Length);
char chData;
char chKey;
char[] data1 = data.ToCharArray();
char[] key1 = key.ToCharArray();
StringBuilder encryptedData = new StringBuilder();
for (int i = 0; i < dataLen; i++)
{
chData = data1[i];
for (int j = 0; j < keyLen; j++)
{
chKey = key1[j];
chData = (char)(chData ^ chKey);
}
encryptedData.Append(chData);
}
return (encryptedData.ToString());
}
But still all in vain. Can anyone tell me how to encrypt it and decrypt the result?
What is the problem you're solving?
Maybe SSL is matching you?
Encryption out of the box, standart solution.
Also you can take a look at JCA. But i think, it will be too heavy solution for your problem.
In my opinion, you should not try to implement a custom algorithm as first off, you're reinventing the wheel, and second off it will probably be no where near as secure as other more standard encryption routines. If I were you, I would take a look around for some good Java Encryption libraries. One I found is here, http://www.bouncycastle.org/latest_releases.html
I have used DES algorith for encryption and decryption.
For encryption:Here after encryption, I am writing file to save. You can save it with other(temp) name and send it to server. After successful sending you can delete this encrypted file
FileOutputStream fos = null ;
CipherInputStream cis;
byte key[] = "abcdEFGH".getBytes();
SecretKeySpec secretKey = new SecretKeySpec(key,"DES");
Cipher encrypt = Cipher.getInstance("DES/ECB/PKCS5Padding");
encrypt.init(Cipher.ENCRYPT_MODE, secretKey);
InputStream fis = new ByteArrayInputStream(fileData);//Here I am getting file data as byte array. You can convert your file data to InputStream by other way too.
File dataFile = new File(dataDir,fileName); //dataDir is location where my file is stored
if(!dataFile.exists()){
cis = new CipherInputStream(fis,encrypt);
try {
fos = new FileOutputStream(dataFile);
byte[] b = new byte[8];
int i;
while ((i=cis.read(b)) != -1) {
fos.write(b, 0, i);
}
return fileName;
} finally{
try {
if(fos != null)
{
fos.flush();
fos.close();
}
cis.close();
fis.close();
} catch (IOException e) {
//IOException
}
}
}
return "";
For decryption:
CipherInputStream cis;
FileOutputStream fos = null;
FileInputStream fis = null;
File dataFile = new File(dataDir,fileName); // here I am getting encrypted file from server
File newDataFile = new File(dataDir,fileName+"_TEMP"); // I am creating temporary decrypted file
byte key[] = "abcdEFGH".getBytes();
SecretKeySpec secretKey = new SecretKeySpec(key,"DES");
Cipher decrypt = Cipher.getInstance("DES/ECB/PKCS5Padding");
decrypt.init(Cipher.DECRYPT_MODE, secretKey);
try {
fis = new FileInputStream(dataFile);
} catch(Exception e) {
//Exception
}
if(dataFile.exists()){
cis = new CipherInputStream(fis,decrypt);
try {
fos = new FileOutputStream(newDataFile);
byte[] b = new byte[8];
int i;
while ((i=cis.read(b)) != -1) {
fos.write(b, 0, i);
}
return newDataFile;
} finally{
try {
if(fos != null)
{
fos.flush();
fos.close(); }
cis.close();
fis.close();
} catch (IOException e) {
//IOException
}
}
}
There are already some answers on SO which might fit you answer.
Encrypt and decrypt a String in java
How to encrypt String in Java
Why dont you use Twofish for that, XML is Text and all you need to use is the algorithm and you can find alot of examples for that.

Categories