/* * File : Encryption.java * Created : 03-jul-2001 09:51 * By : allastar * * JClic - Authoring and playing system for educational activities * * Copyright (C) 2000 - 2005 Francesc Busquets & Departament * d'Educacio de la Generalitat de Catalunya * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details (see the LICENSE file). */ package edu.xtec.util; /** * Utilities to encrypt and decrypt strings using simple methods, just to avoid write * passwords in plain text in data and configuration files. Do not use it as a * secure cryptographic system! * @author Albert Llastarri (allastar@xtec.cat) * @version 13.08.08 */ public final class Encryption { private static final String BLANK="___blank___##"; public static String Encrypt(String txt) { if(txt==null || txt.length()==0) txt=BLANK; String result=null; try{ result=codify(txt); } catch(Exception ex){ System.err.println("Error encripting text!"); } return result; } public static String Decrypt(String txt) { if(txt==null || txt.length()==0) return null; String s=decodify(txt); if(BLANK.equals(s)) s=new String(); return s; } private static char hexCharArrayToChar(char[] cA, int fromIndex){ char[] hex=new char[4]; int n=0; for (int i=0;i<=3;i++){ int j=Character.digit(cA[fromIndex+i],16); n=(n*16)+j; } return (char)n; } private static char[] charToHexCharArray(char c){ char[] hex=new char[4]; int j=(int)c; for (int i=3;i>=0;i--){ hex[i]=Character.forDigit(j%16,16); j/=16; } return hex; } private static char[] intToHexCharArray(int c){ char[] hex=new char[2]; int j=(int)c; for (int i=1;i>=0;i--){ hex[i]=Character.forDigit(j%16,16); j/=16; } return hex; } private static int hexCharArrayToInt(char[] cA, int fromIndex){ int n=0; for (int i=0;i<=1;i++){ int j=Character.digit(cA[fromIndex+i],16); n=(n*16)+j; } return n; } private static StringBuilder compressZeros(char[] cA){ int total=0; StringBuilder sb=new StringBuilder(cA.length); int[] zeros=new int[(cA.length+7)/8]; //it will be better to use bytes, but //then it takes the first bit as a sign int j; for (j=0;total<cA.length;j++){ char b=0; for (int i=0;i<=7;i++){ b<<=1; if (total<cA.length){ if (cA[total]=='0') b+=1; else sb.append(cA[total]); } total++; } zeros[j]=(int)b; } return codifyZerosField(zeros,j).append(sb.substring(0)); } private static StringBuilder codifyZerosField(int[] zeros, int length){ String hexZeros=codifyToHex(zeros,length); //hexZeros size is always odd StringBuilder codified=new StringBuilder(); if (hexZeros.length()>1){ char c1=hexZeros.charAt(0); char c2=hexZeros.charAt(1); int num=1; int currentChar=2; while (currentChar<hexZeros.length()){ if (c1==hexZeros.charAt(currentChar) && c2==hexZeros.charAt(currentChar+1) && num<32) num++; else{ //New sequence codified.append(Character.forDigit(num,32)); codified.append(c1); codified.append(c2); num=1; c1=hexZeros.charAt(currentChar); c2=hexZeros.charAt(currentChar+1); } currentChar+=2; } codified.append(Character.forDigit(num,32)); codified.append(c1); codified.append(c2); codified.append("0"); } return codified; } private static String decodifyZerosField(char[] cA){ StringBuilder sb=new StringBuilder(); int num=Character.digit(cA[0],32); int k=0; int i; for (i=0;num!=0;i++){ while (num>0){ sb.append(cA[(i*3)+1]); sb.append(cA[(i*3)+2]); num--; k++; } if (cA.length>((i*3)+3)) num=Character.digit(cA[(i*3)+3],32); else num=0; } for (int j=(i*3)+1;j<cA.length;j++) sb.append(cA[j]); char c=Character.forDigit(k,32); return c+sb.toString(); } private static StringBuilder decompressZeros(char[] cA){ cA=decodifyZerosField(cA).toCharArray(); int numBytesZeros=Character.digit(cA[0],32); int iniNoZeros=(numBytesZeros*2)+1; boolean bFi=false; StringBuilder sb=new StringBuilder(); for (int i=0;i<numBytesZeros && !bFi;i++){ int zeros=hexCharArrayToInt(cA,1+(i*2)); String s=Integer.toBinaryString(zeros); while (s.length()<8) s="0"+s; for (int j=0;j<=7 && !bFi ;j++){ if (s.charAt(j)=='1'){ sb.append('0'); } else if (iniNoZeros<cA.length){ sb.append(cA[iniNoZeros]); iniNoZeros++; } else bFi=true; } } return sb; } private static String codifyToHex(int[] bA, int length){ //char [] cA=s.toCharArray(); char [] cA=new char[length*2]; int j=0; for (int i=0;i<length;i++){ char [] hex=intToHexCharArray(bA[i]); for (int k=0;k<2;k++){ cA[j]=hex[k]; j++; } } String st=new String(cA); return st; } private static char[] codifyToHex(String s){ char [] cA=new char[s.length()*4]; int j=0; for (int i=0;i<s.length();i++){ char [] hex=charToHexCharArray(s.charAt(i)); for (int k=0;k<4;k++){ cA[j]=hex[k]; j++; } } return cA; } private static String decodifyFromHex(StringBuilder sb1){ StringBuilder sb=new StringBuilder(); char [] cA=sb1.toString().toCharArray(); int j=0; for (int i=0;j<sb1.length();i++){ char c=hexCharArrayToChar(cA,j); sb.append(c); j+=4; } return sb.toString(); } private static char[] changeOrder(StringBuilder s){ int m=0; int n=s.length()-1; char [] cA=new char[s.length()];//=s.toCharArray(); for (int i=0;i<s.length();i++){ if ((i%2)==0){ cA[m]=s.charAt(i); m++; } else{ cA[n]=s.charAt(i); n--; } } return cA; } private static char[] unchangeOrder(String s){ int m=0; int n=s.length()-1; char [] cA=new char[s.length()]; for (int i=0;i<s.length();i++){ if ((i%2)==0){ cA[i]=s.charAt(m); m++; } else{ cA[i]=s.charAt(n); n--; } } return cA; } static class TooLargePasswordException extends Exception{ @Override public String toString(){ return "Password mustn't contain over 24 characters!!!"; } } private static String codify(String word) throws TooLargePasswordException{ if (word.length()>24) throw new TooLargePasswordException(); return new String(changeOrder(compressZeros(codifyToHex(word)))); } private static String decodify(String word){ try{ return decodifyFromHex(decompressZeros(unchangeOrder(word))); } catch (Exception e){ //The supplied word was not codified using this system return ""; } } }