OSDN Git Service

Updated comments in some of the code.
[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 //**********************************************\r
22 //**********************************************\r
23 //* Utility used to encript or decrypt the \r
24 //* text in a note.\r
25 //**********************************************\r
26 //**********************************************\r
27 \r
28 import java.io.IOException;\r
29 import java.security.InvalidAlgorithmParameterException;\r
30 import java.security.InvalidKeyException;\r
31 import java.security.MessageDigest;\r
32 import java.security.NoSuchAlgorithmException;\r
33 import java.util.zip.CRC32;\r
34 \r
35 import javax.crypto.BadPaddingException;\r
36 import javax.crypto.Cipher;\r
37 import javax.crypto.IllegalBlockSizeException;\r
38 import javax.crypto.NoSuchPaddingException;\r
39 import javax.crypto.spec.RC2ParameterSpec;\r
40 import javax.crypto.spec.SecretKeySpec;\r
41 \r
42 import cx.fbn.nevernote.utilities.Base64;\r
43 \r
44 public class EnCrypt {\r
45 \r
46         // Convert a string of text to a hex string\r
47      public static String asHex (byte buf[]) {\r
48       StringBuffer strbuf = new StringBuffer(buf.length * 2);\r
49       int i;\r
50 \r
51       for (i = 0; i < buf.length; i++) {\r
52        if ((buf[i] & 0xff) < 0x10)\r
53             strbuf.append("0");\r
54 \r
55        strbuf.append(Long.toString(buf[i] & 0xff, 16));\r
56       }\r
57 \r
58       return strbuf.toString();\r
59      }\r
60         // Encrypte the text and return the base64 string\r
61         public String encrypt(String text, String passphrase, int keylen) {\r
62                 RC2ParameterSpec parm = new RC2ParameterSpec(keylen);\r
63             MessageDigest md;\r
64                 try {\r
65                         int len = text.length()+4;\r
66                         int mod = (len%8);\r
67                         if (mod>0) {\r
68                                 for (; mod !=0; len++) {\r
69                                         mod = len%8;\r
70                                 }\r
71                                 len--;\r
72                         }\r
73                         len = len-4;\r
74                         StringBuffer textBuffer = new StringBuffer(text);\r
75                         textBuffer.setLength(len);\r
76                         // Get a MD5 for the passphrase\r
77                         md = MessageDigest.getInstance("MD5");\r
78                     md.update(passphrase.getBytes());\r
79                     \r
80                     // Setup parms for the cipher\r
81                     SecretKeySpec skeySpec = new SecretKeySpec(md.digest(), "RC2");\r
82                         Cipher cipher = Cipher.getInstance("RC2/ECB/NoPadding");\r
83                         cipher.init(Cipher.ENCRYPT_MODE, skeySpec, parm);\r
84                         String encoded = crcHeader(textBuffer.toString()) +textBuffer;\r
85                         byte[] d = cipher.doFinal(encoded.getBytes());\r
86                         return Base64.encodeBytes(d);\r
87                 } catch (NoSuchAlgorithmException e) {\r
88                         e.printStackTrace();\r
89                 } catch (NoSuchPaddingException e) {\r
90                         e.printStackTrace();\r
91                 } catch (InvalidKeyException e) {\r
92                         e.printStackTrace();\r
93                 } catch (InvalidAlgorithmParameterException e) {\r
94                         e.printStackTrace();\r
95                 } catch (IllegalBlockSizeException e) {\r
96                         e.printStackTrace();\r
97                 } catch (BadPaddingException e) {\r
98                         e.printStackTrace();\r
99                 }               \r
100                 \r
101                 return null;\r
102         }\r
103         // Decrypt the base64 text and return the unsecure text\r
104         public String decrypt(String text, String passphrase, int keylen) {\r
105                 RC2ParameterSpec parm = new RC2ParameterSpec(keylen);\r
106             MessageDigest md;\r
107                 try {\r
108                         // Get a MD5 for the passphrase\r
109                         md = MessageDigest.getInstance("MD5");\r
110                         StringBuffer p = new StringBuffer(passphrase);\r
111                         md.update(p.toString().getBytes());\r
112                     \r
113                     // Setup parms for the cipher\r
114                     SecretKeySpec skeySpec = new SecretKeySpec(md.digest(), "RC2");\r
115                         Cipher cipher = Cipher.getInstance("RC2/ECB/NOPADDING");\r
116                         cipher.init(Cipher.DECRYPT_MODE, skeySpec, parm);\r
117                         \r
118                         // Decode the encrypted text and decrypt\r
119                         byte[] dString = Base64.decode(text);\r
120                         byte[] d = cipher.doFinal(dString);\r
121                         \r
122                         // We have a result.  Separate it into the 4 byte header and the decrypted text\r
123                         StringBuffer buffer = new StringBuffer(new String(d));\r
124                         String cryptCRC = buffer.substring(0,4);\r
125                         String clearText = buffer.substring(4);\r
126                         String realCRC = crcHeader(clearText);\r
127                         // We need to get the real CRC of the decrypted text\r
128                         if (realCRC.equalsIgnoreCase(cryptCRC)) {\r
129                                 int endPos = clearText.length();\r
130                                 for (int i=buffer.length()-1; i>=0; i--) {\r
131                                         if (buffer.charAt(i) == 0) \r
132                                                 endPos--;\r
133                                         else\r
134                                                 i=-1;\r
135                                 }\r
136                                 clearText = clearText.substring(0,endPos);\r
137                                 return clearText;\r
138                         }\r
139                 } catch (NoSuchAlgorithmException e) {\r
140                         e.printStackTrace();\r
141                 } catch (NoSuchPaddingException e) {\r
142                         e.printStackTrace();\r
143                 } catch (InvalidKeyException e) {\r
144                         e.printStackTrace();\r
145                 } catch (InvalidAlgorithmParameterException e) {\r
146                         e.printStackTrace();\r
147                 } catch (IllegalBlockSizeException e) {\r
148                         e.printStackTrace();\r
149                 } catch (BadPaddingException e) {\r
150                         e.printStackTrace();\r
151                 } catch (IOException e) {\r
152                         // TODO Auto-generated catch block\r
153                         e.printStackTrace();\r
154                 }                       \r
155                 return null;\r
156         }\r
157         // Utility function to return the CRC header of an encoded string.  This is\r
158         // used to verify good decryption and put in front of a new encrypted string\r
159         private String crcHeader(String text) {\r
160                 CRC32 crc = new CRC32();\r
161                 crc.update(text.getBytes());\r
162                 int realCRC = (int)crc.getValue();\r
163                 \r
164                 // The first 4 chars of the hex string will equal the first\r
165                 // 4 chars of the decyphered text.  If they match we have a\r
166                 // good password.  This is what we return\r
167                 realCRC = realCRC ^ (-1);\r
168                 realCRC = realCRC >>> 0;\r
169                 String hexCRC = Integer.toHexString(realCRC).substring(0,4);\r
170                 return hexCRC.toString().toUpperCase();\r
171 \r
172         }\r
173 \r
174 }\r