Package cx.fbn.nevernote.evernote

Source Code of cx.fbn.nevernote.evernote.EnCrypt

/*
* This file is part of NeverNote
* Copyright 2009 Randy Baumgarte
*
* This file may be licensed under the terms of of the
* GNU General Public License Version 2 (the ``GPL'').
*
* Software distributed under the License is distributed
* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
* express or implied. See the GPL for the specific language
* governing rights and limitations.
*
* You should have received a copy of the GPL along with this
* program. If not, go to http://www.gnu.org/licenses/gpl.html
* or write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
package cx.fbn.nevernote.evernote;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.zip.CRC32;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.RC2ParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import cx.fbn.nevernote.utilities.Base64;

public class EnCrypt {

  // Convert a string of text to a hex string
     public static String asHex (byte buf[]) {
      StringBuffer strbuf = new StringBuffer(buf.length * 2);
      int i;

      for (i = 0; i < buf.length; i++) {
       if ((buf[i] & 0xff) < 0x10)
      strbuf.append("0");

       strbuf.append(Long.toString(buf[i] & 0xff, 16));
      }

      return strbuf.toString();
     }

//  public static class EnCryptException extends Exception {
//       public EnCryptException(String message, Throwable cause) {
//         super(message, cause);
//       }
//     }
    
     /**
      * Choose the character set to use for encoding
      */
     private Charset getCharset() {
      
       // Just hard-coding choice here
      boolean useUtf8 = true;
    
     final Charset charSet;
     if(useUtf8) {
       charSet = Charset.forName("UTF-8");
     } else {
       charSet = Charset.defaultCharset();
     }
     return charSet;
     }
    
    
     // Useful for debugging, but not normally used
     @SuppressWarnings("unused")
  private byte[] encodeStringOld(String text) {

       int len = text.length()+4;
       int mod = (len%8);
       if (mod>0) {
         for (; mod !=0; len++) {
           mod = len%8;
         }
         len--;
       }
       len = len-4;
       StringBuffer textBuffer = new StringBuffer(text);
       textBuffer.setLength(len);

       // Setup parms for the cipher
       String encoded = crcHeader(textBuffer.toString()) +textBuffer;

       return encoded.getBytes();
     }

     /**
      * Main changes are
      *
      * 1. Do padding based on encoded bytes, not string length (some chars -> 2 bytes)
      * 2. Use specific named charset
      */
     private byte[] encodeStringNew(String text) {
      
       final Charset charSet = getCharset();
    
     // Convert to bytes using given encoding, and align *bytes* to multiple of
     // 8, with 4 bytes reserved for the crc
     final byte[] bytes = text.getBytes(charSet);
     int align8 = (bytes.length + 4) % 8;
     int paddingNeeded = 8 - align8;
     final byte[] paddedBytes = Arrays.copyOf(bytes, bytes.length + paddingNeeded);
    
     // Now calculate the crc, using the bytes
     String crc = crcHeader(paddedBytes);
    
     byte[] crcBytes = crc.getBytes(charSet);
     if(crcBytes.length != 4) {
       System.err.println("CRC Bytes really should be 4 in length!");
       return null;
     }
    
     // Now combine crc bytes and string bytes into byte array
     // for encryption
     byte[] total = new byte[paddedBytes.length + crcBytes.length];
     System.arraycopy(crcBytes, 0, total, 0, crcBytes.length);
     System.arraycopy(paddedBytes, 0, total, crcBytes.length, paddedBytes.length);
    
     return total;
     }

    
     /**
      * Same as for encryption: use named charset, and
      * @param bytes
      * @return
      */
     private String decodeBytesNew(byte[] bytes) {
      
       Charset charSet = getCharset();
      
       byte[] crcBytes = Arrays.copyOfRange(bytes, 0, 4);
       byte[] textBytes = Arrays.copyOfRange(bytes, 4, bytes.length);
      
       CharBuffer crcChar = charSet.decode(ByteBuffer.wrap(crcBytes));
       CharBuffer textChar = charSet.decode(ByteBuffer.wrap(textBytes));
      
       // Get crc of text to see if same
       String cryptCRC = crcChar.toString();
       String realCRC = crcHeader(textBytes);
      
       if(realCRC.equals(cryptCRC)) {
         // Trim nulls at end
         while(textChar.get(textChar.limit() - 1) == 0 && textChar.limit() != 0) {
           textChar.limit(textChar.limit() - 1);
         }
         String str = textChar.toString();
         return str;
       }
      
       return null;
     }
    
     /** 
      * For reference: old version.  Useful for debugging
      * @param bytes
      * @return
      */ 
     @SuppressWarnings("unused")
  private String decodeBytesOld(byte[] bytes) {

       // We have a result.  Separate it into the 4 byte header and the decrypted text
       StringBuffer buffer = new StringBuffer(new String(bytes));
       String cryptCRC = buffer.substring(0,4);
       String clearText = buffer.substring(4);
       String realCRC = crcHeader(clearText);
       // We need to get the real CRC of the decrypted text
       if (realCRC.equalsIgnoreCase(cryptCRC)) {
         int endPos = clearText.length();
         for (int i=buffer.length()-1; i>=0; i--) {
           if (buffer.charAt(i) == 0)
             endPos--;
           else
             i=-1;
         }
         clearText = clearText.substring(0,endPos);
         return clearText;
       }

       return null;

     }

    
    
  // Encrypte the text and return the base64 string
  public String encrypt(String text, String passphrase, int keylen) {
   
   
    RC2ParameterSpec parm = new RC2ParameterSpec(keylen);
    
    try {
      // Get a MD5 for the passphrase
       MessageDigest md = MessageDigest.getInstance("MD5");
       // NB Use specific Charset
        md.update(passphrase.getBytes(getCharset()));
       
        // Setup parms for the cipher
        SecretKeySpec skeySpec = new SecretKeySpec(md.digest(), "RC2");
      Cipher cipher = Cipher.getInstance("RC2/ECB/NoPadding");
      cipher.init(Cipher.ENCRYPT_MODE, skeySpec, parm);
     
      //byte[] oldBytes = encodeStringOld(text);
      byte[] newBytes = encodeStringNew(text);
      //boolean areSame = Arrays.equals(oldBytes, newBytes);
      //System.out.println("Same? " + areSame);
      byte[] d = cipher.doFinal(newBytes);
     
      return Base64.encodeBytes(d);
    } catch (NoSuchAlgorithmException e) {
      e.printStackTrace();
    } catch (NoSuchPaddingException e) {
      e.printStackTrace();
    } catch (InvalidKeyException e) {
      e.printStackTrace();
    } catch (InvalidAlgorithmParameterException e) {
      e.printStackTrace();
    } catch (IllegalBlockSizeException e) {
      e.printStackTrace();
    } catch (BadPaddingException e) {
      e.printStackTrace();
    }   
   
    return null;
  }
  // Decrypt the base64 text and return the unsecure text
  public String decrypt(String text, String passphrase, int keylen) {
    RC2ParameterSpec parm = new RC2ParameterSpec(keylen);
      MessageDigest md;
    try {
      // Get a MD5 for the passphrase
      md = MessageDigest.getInstance("MD5");
      md.update(passphrase.getBytes(getCharset()));
       
        // Setup parms for the cipher
        SecretKeySpec skeySpec = new SecretKeySpec(md.digest(), "RC2");
      Cipher cipher = Cipher.getInstance("RC2/ECB/NOPADDING");
      cipher.init(Cipher.DECRYPT_MODE, skeySpec, parm);
     
      // Decode the encrypted text and decrypt
      byte[] dString = Base64.decode(text);
      byte[] d = cipher.doFinal(dString);
     
      //String clearTextOld = decodeBytesOld(d);
      String clearTextNew = decodeBytesNew(d);
      //if(clearTextNew != null) {
      //  System.out.println("Are same decrypted ? " + clearTextNew.equals(clearTextOld));
      //}
      return clearTextNew;
    } catch (NoSuchAlgorithmException e) {
      e.printStackTrace();
    } catch (NoSuchPaddingException e) {
      e.printStackTrace();
    } catch (InvalidKeyException e) {
      e.printStackTrace();
    } catch (InvalidAlgorithmParameterException e) {
      e.printStackTrace();
    } catch (IllegalBlockSizeException e) {
      e.printStackTrace();
    } catch (BadPaddingException e) {
      e.printStackTrace();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }     
    return null;
  }
  // Utility function to return the CRC header of an encoded string.  This is
  // used to verify good decryption and put in front of a new encrypted string
  private String crcHeader(String text) {
    return crcHeader(text.getBytes());
  }
  private String crcHeader(byte[] bytes) {
    CRC32 crc = new CRC32();
    crc.update(bytes);
    int realCRC = (int)crc.getValue();
   
    // The first 4 chars of the hex string will equal the first
    // 4 chars of the decyphered text.  If they match we have a
    // good password.  This is what we return
    realCRC = realCRC ^ (-1);
    realCRC = realCRC >>> 0;
    String hexCRC = Integer.toHexString(realCRC).substring(0,4);
    return hexCRC.toString().toUpperCase();

  }

}
TOP

Related Classes of cx.fbn.nevernote.evernote.EnCrypt

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.