OSDN Git Service

Correct problem parsing notes where carriage returns did not separate some XML lines...
[neighbornote/NeighborNote.git] / src / cx / fbn / nevernote / evernote / EnCrypt.java
1 /*\r
2  * This file is part of NeverNote \r
3  * Copyright 2009 Randy Baumgarte\r
4  * \r
5  * This file may be licensed under the terms of of the\r
6  * GNU General Public License Version 2 (the ``GPL'').\r
7  *\r
8  * Software distributed under the License is distributed\r
9  * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either\r
10  * express or implied. See the GPL for the specific language\r
11  * governing rights and limitations.\r
12  *\r
13  * You should have received a copy of the GPL along with this\r
14  * program. If not, go to http://www.gnu.org/licenses/gpl.html\r
15  * or write to the Free Software Foundation, Inc.,\r
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\r
17  *\r
18 */\r
19 package cx.fbn.nevernote.evernote;\r
20 \r
21 import java.io.IOException;\r
22 import java.security.InvalidAlgorithmParameterException;\r
23 import java.security.InvalidKeyException;\r
24 import java.security.MessageDigest;\r
25 import java.security.NoSuchAlgorithmException;\r
26 import java.util.zip.CRC32;\r
27 \r
28 import javax.crypto.BadPaddingException;\r
29 import javax.crypto.Cipher;\r
30 import javax.crypto.IllegalBlockSizeException;\r
31 import javax.crypto.NoSuchPaddingException;\r
32 import javax.crypto.spec.RC2ParameterSpec;\r
33 import javax.crypto.spec.SecretKeySpec;\r
34 \r
35 import cx.fbn.nevernote.utilities.Base64;\r
36 \r
37 public class EnCrypt {\r
38 \r
39         // Convert a string of text to a hex string\r
40      public static String asHex (byte buf[]) {\r
41       StringBuffer strbuf = new StringBuffer(buf.length * 2);\r
42       int i;\r
43 \r
44       for (i = 0; i < buf.length; i++) {\r
45        if ((buf[i] & 0xff) < 0x10)\r
46             strbuf.append("0");\r
47 \r
48        strbuf.append(Long.toString(buf[i] & 0xff, 16));\r
49       }\r
50 \r
51       return strbuf.toString();\r
52      }\r
53         // Encrypte the text and return the base64 string\r
54         public String encrypt(String text, String passphrase, int keylen) {\r
55                 RC2ParameterSpec parm = new RC2ParameterSpec(keylen);\r
56             MessageDigest md;\r
57                 try {\r
58                         int len = text.length()+4;\r
59                         int mod = (len%8);\r
60                         if (mod>0) {\r
61                                 for (; mod !=0; len++) {\r
62                                         mod = len%8;\r
63                                 }\r
64                                 len--;\r
65                         }\r
66                         len = len-4;\r
67                         StringBuffer textBuffer = new StringBuffer(text);\r
68                         textBuffer.setLength(len);\r
69                         // Get a MD5 for the passphrase\r
70                         md = MessageDigest.getInstance("MD5");\r
71                     md.update(passphrase.getBytes());\r
72                     \r
73                     // Setup parms for the cipher\r
74                     SecretKeySpec skeySpec = new SecretKeySpec(md.digest(), "RC2");\r
75                         Cipher cipher = Cipher.getInstance("RC2/ECB/NoPadding");\r
76                         cipher.init(Cipher.ENCRYPT_MODE, skeySpec, parm);\r
77                         String encoded = crcHeader(textBuffer.toString()) +textBuffer;\r
78                         byte[] d = cipher.doFinal(encoded.getBytes());\r
79                         return Base64.encodeBytes(d);\r
80                 } catch (NoSuchAlgorithmException e) {\r
81                         e.printStackTrace();\r
82                 } catch (NoSuchPaddingException e) {\r
83                         e.printStackTrace();\r
84                 } catch (InvalidKeyException e) {\r
85                         e.printStackTrace();\r
86                 } catch (InvalidAlgorithmParameterException e) {\r
87                         e.printStackTrace();\r
88                 } catch (IllegalBlockSizeException e) {\r
89                         e.printStackTrace();\r
90                 } catch (BadPaddingException e) {\r
91                         e.printStackTrace();\r
92                 }               \r
93                 \r
94                 return null;\r
95         }\r
96         // Decrypt the base64 text and return the unsecure text\r
97         public String decrypt(String text, String passphrase, int keylen) {\r
98                 RC2ParameterSpec parm = new RC2ParameterSpec(keylen);\r
99             MessageDigest md;\r
100                 try {\r
101                         // Get a MD5 for the passphrase\r
102                         md = MessageDigest.getInstance("MD5");\r
103                         StringBuffer p = new StringBuffer(passphrase);\r
104                         md.update(p.toString().getBytes());\r
105                     \r
106                     // Setup parms for the cipher\r
107                     SecretKeySpec skeySpec = new SecretKeySpec(md.digest(), "RC2");\r
108                         Cipher cipher = Cipher.getInstance("RC2/ECB/NOPADDING");\r
109                         cipher.init(Cipher.DECRYPT_MODE, skeySpec, parm);\r
110                         \r
111                         // Decode the encrypted text and decrypt\r
112                         byte[] dString = Base64.decode(text);\r
113                         byte[] d = cipher.doFinal(dString);\r
114                         \r
115                         // We have a result.  Separate it into the 4 byte header and the decrypted text\r
116                         StringBuffer buffer = new StringBuffer(new String(d));\r
117                         String cryptCRC = buffer.substring(0,4);\r
118                         String clearText = buffer.substring(4);\r
119                         String realCRC = crcHeader(clearText);\r
120                         // We need to get the real CRC of the decrypted text\r
121                         if (realCRC.equalsIgnoreCase(cryptCRC)) {\r
122                                 int endPos = clearText.length();\r
123                                 for (int i=buffer.length()-1; i>=0; i--) {\r
124                                         if (buffer.charAt(i) == 0) \r
125                                                 endPos--;\r
126                                         else\r
127                                                 i=-1;\r
128                                 }\r
129                                 clearText = clearText.substring(0,endPos);\r
130                                 return clearText;\r
131                         }\r
132                 } catch (NoSuchAlgorithmException e) {\r
133                         e.printStackTrace();\r
134                 } catch (NoSuchPaddingException e) {\r
135                         e.printStackTrace();\r
136                 } catch (InvalidKeyException e) {\r
137                         e.printStackTrace();\r
138                 } catch (InvalidAlgorithmParameterException e) {\r
139                         e.printStackTrace();\r
140                 } catch (IllegalBlockSizeException e) {\r
141                         e.printStackTrace();\r
142                 } catch (BadPaddingException e) {\r
143                         e.printStackTrace();\r
144                 } catch (IOException e) {\r
145                         // TODO Auto-generated catch block\r
146                         e.printStackTrace();\r
147                 }                       \r
148                 return null;\r
149         }\r
150         // Utility function to return the CRC header of an encoded string.  This is\r
151         // used to verify good decryption and put in front of a new encrypted string\r
152         private String crcHeader(String text) {\r
153                 CRC32 crc = new CRC32();\r
154                 crc.update(text.getBytes());\r
155                 int realCRC = (int)crc.getValue();\r
156                 \r
157                 // The first 4 chars of the hex string will equal the first\r
158                 // 4 chars of the decyphered text.  If they match we have a\r
159                 // good password.  This is what we return\r
160                 realCRC = realCRC ^ (-1);\r
161                 realCRC = realCRC >>> 0;\r
162                 String hexCRC = Integer.toHexString(realCRC).substring(0,4);\r
163                 return hexCRC.toString().toUpperCase();\r
164 \r
165         }\r
166 \r
167 }\r