I have a program which is encrypting a text file and saves the encoded txt and the key seperatly. Now I try to write the decrypting program which is using the key to decode the file. I read in the key, but it seems I can't really use it like that. Has anyone suggestions for me, or isn't it even possible to do it like this?
public class decrypt {
public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IOException {
try {
File fileDir = new File("C:/xxx/key.txt");
BufferedReader in = new BufferedReader(
new InputStreamReader(new FileInputStream(fileDir), "UTF-8"));
String str;
while ((str = in.readLine()) != null) {
System.out.println(str);
}
in.close();
}catch (UnsupportedEncodingException e){
System.out.println(e.getMessage());
}catch (IOException e){
System.out.println(e.getMessage());
}catch (Exception e){
System.out.println(e.getMessage());
}
byte[] decodedKey = Base64.getDecoder().decode(str);
SecretKey originalKey = new SecretKeySpec(decodedKey, 0, decodedKey.length, "AES");
}
}
decrypt a textfile
Your question already doesn't make sense. The result of encryption is not a text file. So you have no business trying to read it with a Reader in the first place.
You need to have a good look at CipherInputStream.
str = in.readLine() doesn't append text to str, but creates a new string containing the next line instead.
You should do the following:
StringBuilder sb = new StringBuilder();
Then in the while-loop:
sb.append(str);
And in the end you can get your string content by calling
sb.toString()
EDIT: Or if it's clearer this way, a more complete example:
String line;
StringBuilder sb = new StringBuilder();
while ((line = in.readLine()) != null) {
sb.append(line);
sb.append("\n");
System.out.println(line);
}
String content = sb.toString();
Related
I am having a very weird issue.
I am putting and getting messages from Amazon AWS SQS.
While putting I am compressing and encoding the messages, like this :
String responseMessageBodyOriginal = gson.toJson(responseData);
String responseMessageBodyCompressed = compressToBase64String(responseMessageBodyOriginal);
AmazonSqsHelper.sendMessage(responseMessageBodyCompressed, queue, null);
Compression and encoding function, looks like this :
public static String compressToBase64String(String data) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream(data.length());
GZIPOutputStream gzip = new GZIPOutputStream(bos);
gzip.write(data.getBytes());
gzip.close();
byte[] compressedBytes = bos.toByteArray();
bos.close();
return new String(Base64.encodeBase64(compressedBytes));
}
On the other hand, while receiving message, this is the code :
List<Message> sqsMessageList = AmazonSqsHelper.receiveMessages(queueUrl, max_message_read_count,
default_visibility_timeout);
int num_messages = sqsMessageList.size();
if (num_messages > 0) {
for (Message m : sqsMessageList) {
String responseMessageBodyCompressed = m.getBody();
String responseMessageBodyOriginal = decompressFromBase64String(responseMessageBodyCompressed);
}
}
And the function used for decoding and unzipping is like this :
public static String decompressFromBase64String(String compressedString) throws IOException {
byte[] compressedBytes = Base64.decodeBase64(compressedString);
ByteArrayInputStream bis = new ByteArrayInputStream(compressedBytes);
GZIPInputStream gis = new GZIPInputStream(bis);
BufferedReader br = new BufferedReader(new InputStreamReader(gis, "UTF-8"));
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(line);
}
br.close();
gis.close();
bis.close();
return sb.toString();
}
But the problem is , at times if I pass characters like "â®" then those are getting converted to ???? , after decoding if I am printing the message.
Not able to figure out why encoding and decoding is behaving weird. Any help would be appreciated.
Issue is that encoding is done using the platform's default charset (data.getBytes()), while decoding - using UTF-8.
In compressToBase64String change data.getBytes() to data.getBytes(StandardCharsets.UTF_8).
This question already has answers here:
Getting a File's MD5 Checksum in Java
(22 answers)
Closed 7 years ago.
I wrote the following program to calculate SHA-256 hash value of a string in Java:
public class ToHash {
public static void main(String[] args) {
byte[] data = "test".getBytes("UTF8");
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(data);
System.out.println(new BASE64Encoder().encode(hash));
}
}
Well, that works fine. In the next step I want to develop it in a way to accept a file and calculate its hash value. My solution is to read whole the file in a string array and the call the digest() method on that string array. But there are two problems :
I don't have any idea how to read whole the file into an array? Currently I think I must read it line by line and append an array with the new lines!
Above methodology need a lot of memory for big files!
This is my current program to read a file:
public class ToHash {
public static void main(String[] args) throws NoSuchAlgorithmException, UnsupportedEncodingException, FileNotFoundException, IOException {
// TODO code application logic here
// The name of the file to open.
String fileName = "C:\\Users\\ghasemi\\Desktop\\1.png";
BufferedReader br = null;
try {
String sCurrentLine;
br = new BufferedReader(new FileReader(fileName));
while ((sCurrentLine = br.readLine()) != null) {
byte[] data = sCurrentLine.getBytes("UTF8");
System.out.println(new BASE64Encoder().encode(data));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (br != null) {
br.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
It seems that there is no method for BufferedReader object to read whole the file with one call.
You can read the file and calculate the value of the hash as you go.
byte[] buffer= new byte[8192];
int count;
MessageDigest digest = MessageDigest.getInstance("SHA-256");
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(fileName));
while ((count = bis.read(buffer)) > 0) {
digest.update(buffer, 0, count);
}
bis.close();
byte[] hash = digest.digest();
System.out.println(new BASE64Encoder().encode(hash));
This doesn't assume anything about character sets or about the file fitting into memory, and it doesn't ignore line terminators either.
Or you can use a DigestInputStream.
I tried putting a toast before the return statement but the String variable returns an empty string.
public String getXmlFile(String pathFile, Context context){
String xmlFileString = "";
AssetManager am = context.getAssets();
try {
InputStream str = am.open(pathFile);
int length = str.available();
byte[] data = new byte[length];
xmlFileString = new String(data);
} catch (IOException e1) {
e1.printStackTrace();
}
return xmlFileString;
}
use this to read byte[] from InputStream:
public byte[] convertStreamToString(InputStream is) throws Exception {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
is.close();
return sb.toString().getBytes("UTF-8");
}
Use this to read the XML. Without passing UTF-8 to the InputStreamReader you might get a broken XML string.
BufferedReader reader = new BufferedReader(new InputStreamReader(
context.getAssets().open(pathFile), HTTP.UTF_8));
StringBuilder sb = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
reader.close();
Now when parsing the string to XML in my case there was also the problem that each line break was interpreted as an own XML node. Spaces also were an issue. Use this on the string read above to fix that:
String oneLineXml = sb.toString().replace("\n", "").replaceAll("> +<", "><");
Only then you should parse the string, like this:
Document xml = DocumentBuilderFactory.newInstance().newDocumentBuilder()
.parse(new InputSource(new ByteArrayInputStream(
oneLineXml.getBytes(HTTP.UTF_8))));
I am trying to start a simple session with grooveshark and am using the sendPostReq function to call the startSession api. I keep on getting the following response from grooveshark.
{"errors":[{"code":2,"message":"Method not found."}]}
The way we work with the grooveshark api is we have the payload(grooveSharkjson in my case), we produce a md5 hash of that using the secret key and post that json to this url https://api.grooveshark.com/ws3.php?sig={md5-hash-of-payload}. Is that the correct procedure?
The sendPostReq function and the code for producing the md5 hash is also present below
public static void sendPostReq() throws Exception{
String grooveSharkjson = "{'method':'startSession','header':{'wsKey':'wskey'}}";
String key = "secret"; // Your api key.
String sig = SecurityHelper.getHmacMD5(grooveSharkjson, key);
URL url = new URL("https://api.grooveshark.com/ws3.php?sig=" + sig);
URLConnection connection = url.openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
connection.connect();
OutputStream os = connection.getOutputStream();
PrintWriter pw = new PrintWriter(new OutputStreamWriter(os));
pw.write(grooveSharkjson);
pw.close();
InputStream is = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String line = null;
StringBuffer sb = new StringBuffer();
while ((line = reader.readLine()) != null) {
sb.append(line);
}
is.close();
String response = sb.toString();
System.out.println(response);
}
public static String getHmacMD5(String payload, String secret) {
String sEncodedString = null;
try {
SecretKeySpec key = new SecretKeySpec((secret).getBytes("UTF-8"), "HmacMD5");
Mac mac = Mac.getInstance("HmacMD5");
mac.init(key);
byte[] bytes = mac.doFinal(payload.getBytes("UTF-8"));
StringBuffer hash = new StringBuffer();
for (int i=0; i<bytes.length; i++) {
String hex = Integer.toHexString(0xFF & bytes[i]);
if (hex.length() == 1) {
hash.append('0');
}
hash.append(hex);
}
sEncodedString = hash.toString();
}
catch (UnsupportedEncodingException e) {}
catch(InvalidKeyException e){}
catch (NoSuchAlgorithmException e) {}
return sEncodedString ;
}
I believe the hash I am producing is correct as I have verified it with the sample key and secret they have supplied us with on their website
http://developers.grooveshark.com/tuts/public_api
I know I posted the question about 20 mins back, but I just found the solution. There was a problem with the json string, especially the way I was generating it. This is how it should be generated
String grooveSharkjson = "{\"method\":\"startSession\",\"header\":{\"wsKey\":\"wsKey\"},\"parameters\":[]}";
I did not expect the solution to be so obvious but this is from where I got an idea of how to solve my problem - I tested my key and secret on their sandbox (http://developers.grooveshark.com/docs/public_api/v3/sandbox.php) and double checked the hmac md5 signature.
I have the following code, which will read in files in ISO-8859-1, as thats what is required in this application,
private static String readFile(String filename) throws IOException {
String lineSep = System.getProperty("line.separator");
File f = new File(filename);
StringBuffer sb = new StringBuffer();
if (f.exists()) {
BufferedReader br =
new BufferedReader(
new InputStreamReader(
new FileInputStream(filename), "ISO-8859-1"));
String nextLine = "";
while ((nextLine = br.readLine()) != null) {
sb.append(nextLine+ " ");
// note: BufferedReader strips the EOL character.
// sb.append(lineSep);
}
br.close();
}
return sb.toString();
}
The problem is it is pretty slow. I have this function, which is MUCH faster, but I can not seem to find how to place the character encoding:
private static String fastStreamCopy(String filename)
{
String s = "";
FileChannel fc = null;
try
{
fc = new FileInputStream(filename).getChannel();
MappedByteBuffer byteBuffer = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
int size = byteBuffer.capacity();
if (size > 0)
{
byteBuffer.clear();
byte[] bytes = new byte[size];
byteBuffer.get(bytes, 0, bytes.length);
s = new String(bytes);
}
fc.close();
}
catch (FileNotFoundException fnfx)
{
System.out.println("File not found: " + fnfx);
}
catch (IOException iox)
{
System.out.println("I/O problems: " + iox);
}
finally
{
if (fc != null)
{
try
{
fc.close();
}
catch (IOException ignore)
{
}
}
}
return s;
}
Any one have an idea of where i should be putting the ISO encoding?
From the code you posted, you're not trying to "copy" the stream, but read it into a string.
You can simply provide the encoding in the String constructor:
s = new String(bytes, "ISO-88591-1");
Personally I'd just replace the whole method with a call to the Guava method Files.toString():
String content = Files.toString(new File(filename), StandardCharsets.ISO_8859_1);
If you're using Java 6 or earlier, you'll need to use the Guava field Charsets.ISO_8859_1 instead of StandardCharsets.ISO_8859_1 (which was only introduced in Java 7).
However your use of the term "copy" suggests that you want to write the result to some other file (or stream). If that is true, then you don't need to care about the encoding at all, since you can just handle the byte[] directly and avoid the (unnecessary) conversion to and from String.
where you are converting bytes to string e.g. s = new String(bytes, encoding); or vice versa.