1

I'm testing the encryption of text in Java. The problem is that I get some strange characters at the beginning of the line and I don't understand why. When I remove encryption everything goes smoothly.

When copied into Notepad++, the output looks like:

Hello

<SOH>dear

<STX><STX>world

Why am I getting the strange control characters?

Code:

public class Test {
        private static File file;
        private static final byte[] STAT_KEY = { -1, -2, 3, 4, -5, -6, -7, 8 };
        static {
            file = new File("MyFile.txt");
        }

        private static Cipher getCipher(int mode) throws InvalidKeyException, NoSuchAlgorithmException,
                InvalidKeySpecException, NoSuchPaddingException {
            DESKeySpec dks = new DESKeySpec(STAT_KEY);
            SecretKeyFactory skf = SecretKeyFactory.getInstance("DES");
            SecretKey desKey = skf.generateSecret(dks);
            Cipher cipher = Cipher.getInstance("DES");
            cipher.init(mode, desKey);
            return cipher;
        }

        private static void appendToFile(String item) throws Exception {
            CipherOutputStream cos = null;
            try {
                cos = new CipherOutputStream(new FileOutputStream(file, true), getCipher(Cipher.ENCRYPT_MODE));
                cos.write((item + String.format("%n")).getBytes());
            } finally {
                cos.close();
            }
        }

        private static void readFromFile() throws Exception {
            CipherInputStream cis = null;
            try {
                cis = new CipherInputStream(new FileInputStream(file), getCipher(Cipher.DECRYPT_MODE));
                int content;
                while ((content = cis.read()) != -1) {
                    System.out.print((char) content);
                }
            } finally {
                cis.close();
            }
        }

        public static void main(String[] args) throws Exception {
            String[] items = { "Hello", "dear", "world" };
            for (String item : items) {
                appendToFile(item);
            }
            readFromFile();
        }
    }

PD: Excuse the way I deal with exceptions :)

Duncan Jones
  • 67,400
  • 29
  • 193
  • 254
dalvarezmartinez1
  • 1,385
  • 1
  • 17
  • 26

1 Answers1

1

Much like an ObjectOutputStream, the CipherOutputStream is not written in a way that allows direct appending.

append(data1) + append(data2) + append(data3) != append(data1+data2+data3)

You need to add your own method of delimiting different blocks of data. The funny ? characters are the private control characters used by the CipherOutputStream.

Life may be easier if you just encrypt the data normally (i.e. using a Cipher object) and write the output to your file surrounded by suitable delimiters.

Duncan Jones
  • 67,400
  • 29
  • 193
  • 254
  • By appending you mean the cos.write((item + String.format("%n")).getBytes()); line? My goal is to write text by lines, so I was trying to append a new line char, at the end of each string. My English my not be good enough, would you care to provide some code, pseudo-code for the last sentence. How do I encrypt the data normally? I understand that after encryption, I should use a normal FileOutputStream to write this encrypted data to the file. – dalvarezmartinez1 Apr 09 '13 at 15:35
  • Ok, so I think I solved it as you said, I found a way to encrypt a string here: http://stackoverflow.com/questions/1205135/how-to-encrypt-string-in-java And I'm using normal FileOutputStream, to output the result to a file. Now I get some \00\00\00 in front of some words, but probably something to do with padding – dalvarezmartinez1 Apr 09 '13 at 16:41
  • What were you using as the delimiter? Just a newline? – Duncan Jones Apr 10 '13 at 06:52
  • Yes,just a new line,I also realized what you meant with append(data1)+append(data2)!=append(data1+data2). The trick is not to close the CipherOutputStream, as long as you don't close it and after that, try to append again, things are fine.So I'm declaring the CipherOutputStream as a static field,and don't close it after each appending, instead close it when the whole process is over (I have some threads that compete to append stuff to this file).After that I decode the file and all is ok.How did you know that "the CipherOutputStream is not written in a way that allows direct appending"?thanks – dalvarezmartinez1 Apr 10 '13 at 07:41
  • I honestly can't recall why I knew/thought that. Certainly my suspicions were confirmed when I saw the control characters in your output. Glad you've got a solution. – Duncan Jones Apr 10 '13 at 16:30