2012-07-05 04:23:07 -04:00
// cryptbig.java
2005-04-07 15:19:42 -04:00
// -------------------------------------
2008-07-20 13:14:51 -04:00
// (C) by Michael Peter Christen; mc@yacy.net
2005-04-07 15:19:42 -04:00
// first published on http://www.anomic.de
// Frankfurt, Germany, 2004
2011-03-07 20:51:51 -05:00
//
// $LastChangedDate$
// $LastChangedRevision$
// $LastChangedBy$
2005-04-07 15:19:42 -04:00
//
// 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.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2012-09-21 09:48:16 -04:00
package net.yacy.utils ;
2005-04-07 15:19:42 -04:00
2005-05-05 01:32:19 -04:00
import java.io.BufferedInputStream ;
import java.io.BufferedOutputStream ;
import java.io.File ;
import java.io.FileInputStream ;
import java.io.FileNotFoundException ;
import java.io.FileOutputStream ;
import java.io.IOException ;
import java.io.InputStream ;
import java.io.OutputStream ;
import java.io.UnsupportedEncodingException ;
import java.security.Provider ;
import java.security.Security ;
import java.text.ParsePosition ;
import java.text.SimpleDateFormat ;
import java.util.Date ;
import java.util.HashSet ;
import java.util.Iterator ;
import java.util.Locale ;
import java.util.Random ;
import java.util.Set ;
import javax.crypto.BadPaddingException ;
import javax.crypto.Cipher ;
import javax.crypto.CipherInputStream ;
import javax.crypto.CipherOutputStream ;
import javax.crypto.IllegalBlockSizeException ;
import javax.crypto.SecretKey ;
import javax.crypto.SecretKeyFactory ;
import javax.crypto.spec.PBEKeySpec ;
import javax.crypto.spec.PBEParameterSpec ;
2013-09-14 18:30:23 -04:00
import net.yacy.cora.document.encoding.UTF8 ;
2012-09-21 10:46:57 -04:00
import net.yacy.cora.order.Base64Order ;
import net.yacy.cora.order.Digest ;
2012-11-26 07:11:55 -05:00
import net.yacy.cora.util.CommonPattern ;
2013-07-09 08:28:25 -04:00
import net.yacy.cora.util.ConcurrentLog ;
2009-10-09 19:22:22 -04:00
2005-04-07 15:19:42 -04:00
public class cryptbig {
// --------------------------------------------------------
// Section: random salt generation
// --------------------------------------------------------
private static long saltcounter = 0 ;
private static Random saltrandom = new Random ( System . currentTimeMillis ( ) ) ;
public static String randomSalt ( ) {
2006-01-03 19:39:00 -05:00
// generate robust 48-bit random number
2008-08-02 08:12:04 -04:00
final long salt = ( saltrandom . nextLong ( ) & 0XffffffffffffL ) + ( System . currentTimeMillis ( ) & 0XffffffffffffL ) + ( ( 1001 * saltcounter ) & 0XffffffffffffL ) ;
2006-01-03 19:39:00 -05:00
saltcounter + + ;
// we generate 48-bit salt values, that are represented as 8-character
// b64-encoded strings
2011-02-24 19:56:31 -05:00
return Base64Order . standardCoder . encodeLongSB ( salt & 0XffffffffffffL , 8 ) . toString ( ) ;
2005-04-07 15:19:42 -04:00
}
// --------------------------------------------------------
// Section: PBE + PublicKey based on passwords encryption
// --------------------------------------------------------
public static final String vDATE = " 20030925 " ;
public static final String copyright = " [ 'crypt' v " + vDATE + " by Michael Christen / www.anomic.de ] " ;
public static final String magicString = " crypt|anomic.de|0 " ; // magic identifier inside every '.crypt' - file
public static final SimpleDateFormat dateFormatter = new SimpleDateFormat ( " yyyyMMddHHmmssSSS " , Locale . ENGLISH ) ;
String cryptMethod ; // one of ["TripleDES", "Blowfish", "DESede", "DES"]
private static final String defaultMethod = " PBEWithMD5AndDES " ; //"DES";
Cipher ecipher ;
Cipher dcipher ;
2012-07-05 04:23:07 -04:00
2008-08-02 08:12:04 -04:00
public cryptbig ( final String pbe ) {
2005-04-07 15:19:42 -04:00
// this is possible, but not recommended
this ( pbe , ( pbe + " XXXXXXXX " ) . substring ( 0 , 8 ) ) ;
}
2008-08-02 08:12:04 -04:00
public cryptbig ( final String pbe , final String salt ) {
2005-04-07 15:19:42 -04:00
this ( pbe , salt , defaultMethod ) ;
}
2008-08-02 08:12:04 -04:00
private cryptbig ( final String pbe , String salt , final String method ) {
2005-04-07 15:19:42 -04:00
// a Password-Based Encryption. The SecretKey is created on the fly
2008-08-02 08:12:04 -04:00
final PBEKeySpec keySpec = new PBEKeySpec ( pbe . toCharArray ( ) ) ;
2005-04-07 15:19:42 -04:00
try {
if ( salt . length ( ) > 8 ) salt = salt . substring ( 0 , 8 ) ;
if ( salt . length ( ) < 8 ) salt = ( salt + " XXXXXXXX " ) . substring ( 0 , 8 ) ;
2012-07-05 04:23:07 -04:00
2005-04-07 15:19:42 -04:00
// create the PBE key
2008-08-02 08:12:04 -04:00
final SecretKeyFactory keyFactory = SecretKeyFactory . getInstance ( method ) ;
final SecretKey key = keyFactory . generateSecret ( keySpec ) ;
2005-04-07 15:19:42 -04:00
// create parameter spec for PBE
2011-03-10 18:25:07 -05:00
final PBEParameterSpec paramSpec = new PBEParameterSpec ( UTF8 . getBytes ( salt ) , 1000 /*ITERATIONS*/ ) ;
2012-07-05 04:23:07 -04:00
2005-04-07 15:19:42 -04:00
// Create a cipher and initialize it for encrypting end decrypting
2012-07-05 04:23:07 -04:00
this . cryptMethod = method ;
this . ecipher = Cipher . getInstance ( this . cryptMethod ) ;
this . dcipher = Cipher . getInstance ( this . cryptMethod ) ;
this . ecipher . init ( Cipher . ENCRYPT_MODE , key , paramSpec ) ; // paramSpec only for PBE!
this . dcipher . init ( Cipher . DECRYPT_MODE , key , paramSpec ) ;
2008-08-02 08:12:04 -04:00
} catch ( final javax . crypto . NoSuchPaddingException e ) {
} catch ( final java . security . InvalidKeyException e ) {
} catch ( final java . security . NoSuchAlgorithmException e ) {
} catch ( final java . security . spec . InvalidKeySpecException e ) {
} catch ( final java . security . InvalidAlgorithmParameterException e ) {
2005-04-07 15:19:42 -04:00
}
}
2012-07-05 04:23:07 -04:00
2005-04-07 15:19:42 -04:00
// Encode a string into a new string using utf-8, crypt and b64
2008-08-02 08:12:04 -04:00
public String encryptString ( final String str ) {
2005-04-07 15:19:42 -04:00
try {
2008-08-02 08:12:04 -04:00
final byte [ ] utf = str . getBytes ( " UTF8 " ) ;
final byte [ ] enc = encryptArray ( utf ) ;
2005-04-07 15:19:42 -04:00
if ( enc = = null ) return null ;
2009-01-30 10:33:00 -05:00
return Base64Order . standardCoder . encode ( enc ) ;
2008-08-02 08:12:04 -04:00
} catch ( final UnsupportedEncodingException e ) {
2005-04-07 15:19:42 -04:00
}
return null ;
}
// Decode a string into a new string using b64, crypt and utf-8
2008-08-02 08:12:04 -04:00
public String decryptString ( final String str ) {
2011-03-07 15:36:40 -05:00
final byte [ ] b64dec = Base64Order . standardCoder . decode ( str ) ;
if ( b64dec = = null ) return null ; // error in input string (inconsistency)
final byte [ ] dec = decryptArray ( b64dec ) ;
if ( dec = = null ) return null ;
return UTF8 . String ( dec ) ;
2005-04-07 15:19:42 -04:00
}
// Encode a byte array into a new byte array
2008-08-02 08:12:04 -04:00
public byte [ ] encryptArray ( final byte [ ] b ) {
2005-04-07 15:19:42 -04:00
if ( b = = null ) return null ;
try {
2012-07-05 04:23:07 -04:00
return this . ecipher . doFinal ( b ) ;
2008-08-02 08:12:04 -04:00
} catch ( final javax . crypto . BadPaddingException e ) {
} catch ( final IllegalBlockSizeException e ) {
2005-04-07 15:19:42 -04:00
}
return null ;
}
2012-07-05 04:23:07 -04:00
2005-04-07 15:19:42 -04:00
// Decode a string into a new string using b64, crypt and utf-8
2008-08-02 08:12:04 -04:00
public byte [ ] decryptArray ( final byte [ ] b ) {
2005-04-07 15:19:42 -04:00
if ( b = = null ) return null ;
try {
2012-07-05 04:23:07 -04:00
return this . dcipher . doFinal ( b ) ;
2008-08-02 08:12:04 -04:00
} catch ( final javax . crypto . BadPaddingException e ) {
} catch ( final IllegalBlockSizeException e ) {
2005-04-07 15:19:42 -04:00
}
return null ;
}
// This method returns the available implementations for a service type
2008-08-02 08:12:04 -04:00
public static Set < String > listCryptoMethods ( final String serviceType ) {
final Set < String > result = new HashSet < String > ( ) ;
2012-07-05 04:23:07 -04:00
2005-04-07 15:19:42 -04:00
// All providers
2008-08-02 08:12:04 -04:00
final Provider [ ] providers = Security . getProviders ( ) ;
2012-07-05 04:23:07 -04:00
for ( Provider provider : providers ) {
2005-04-07 15:19:42 -04:00
// Get services provided by each provider
2012-07-05 04:23:07 -04:00
final Set < ? > keys = provider . keySet ( ) ;
for ( Object name : keys ) {
String key = ( String ) name ;
2012-11-26 07:11:55 -05:00
key = CommonPattern . SPACE . split ( key ) [ 0 ] ;
2005-04-07 15:19:42 -04:00
if ( key . startsWith ( serviceType + " . " ) ) {
result . add ( key . substring ( serviceType . length ( ) + 1 ) ) ;
} else if ( key . startsWith ( " Alg.Alias. " + serviceType + " . " ) ) {
// This is an alias
result . add ( key . substring ( serviceType . length ( ) + 11 ) ) ;
}
}
}
return result ;
}
2008-08-02 08:12:04 -04:00
public static void testCryptMethods ( final Set < String > methods ) {
2005-04-07 15:19:42 -04:00
String method ;
2008-08-02 08:12:04 -04:00
final Iterator < String > i = methods . iterator ( ) ;
2005-04-07 15:19:42 -04:00
while ( i . hasNext ( ) ) {
2008-06-06 12:01:27 -04:00
method = i . next ( ) ;
2005-04-07 15:19:42 -04:00
System . out . print ( method + " : " ) ;
try {
2008-08-02 08:12:04 -04:00
final cryptbig crypter = new cryptbig ( " abrakadabra " , method ) ;
final String encrypted = crypter . encryptString ( " nicht verraten abc 1234567890 " ) ;
2005-04-07 15:19:42 -04:00
System . out . print ( encrypted + " / " ) ;
2008-08-02 08:12:04 -04:00
final String decrypted = crypter . decryptString ( encrypted ) ;
2005-04-07 15:19:42 -04:00
System . out . println ( decrypted ) ;
2008-08-02 08:12:04 -04:00
} catch ( final Exception e ) {
2005-04-07 15:19:42 -04:00
System . out . println ( " Exception: " + e . getMessage ( ) ) ;
2013-07-09 08:28:25 -04:00
ConcurrentLog . logException ( e ) ;
2005-04-07 15:19:42 -04:00
}
}
}
2012-07-05 04:23:07 -04:00
public void encryptFile ( final String inFileName , final String outFileName ) {
2005-04-07 15:19:42 -04:00
/ *
File - Format of encrypted file :
Filename : b64 - of - encryption - of - < encryption - date : YYYYMMddHHmmSSsss > plus extension " .crypt "
File Content :
< original file name >
< original file date >
< original file size >
< compressed - before - encryption - flag >
< compressed - after - encryption - flag >
< binary >
* /
2017-06-02 22:00:46 -04:00
InputStream fin = null ;
OutputStream fout = null ;
2005-04-07 15:19:42 -04:00
try {
2008-08-02 08:12:04 -04:00
final File inFile = new File ( inFileName ) ;
final String inFileDate = dateFormatter . format ( new Date ( inFile . lastModified ( ) ) ) ; // 17 byte
final String encryptionDate = dateFormatter . format ( new Date ( ) ) ; // 17 byte
2011-02-24 19:56:31 -05:00
final String inFileSize = Base64Order . standardCoder . encodeLongSB ( inFile . length ( ) , 11 ) . toString ( ) ; // 64 / 6 = 11; 11 byte
2008-08-02 08:12:04 -04:00
final String flag = " 1 " ; // 1 byte
2005-12-04 18:51:28 -05:00
//int inFileNameLength = inFileName.length(); // 256
2008-08-02 08:12:04 -04:00
final String X = inFileDate + encryptionDate + inFileSize + flag + inFileName ;
2005-04-07 15:19:42 -04:00
System . out . println ( " TEST: preserving inFileDate : " + dateFormatter . parse ( inFileDate , new ParsePosition ( 0 ) ) ) ;
System . out . println ( " TEST: preserving encryptionDate: " + dateFormatter . parse ( encryptionDate , new ParsePosition ( 0 ) ) ) ;
System . out . println ( " TEST: preserving inFileLength : " + inFile . length ( ) ) ;
System . out . println ( " TEST: preserving flag : " + flag ) ;
System . out . println ( " TEST: preserving inFileName : " + inFileName ) ;
System . out . println ( " TEST: preserving X-String : " + X ) ;
// start encryption
2017-06-02 22:00:46 -04:00
fin = new CipherInputStream ( new FileInputStream ( inFile ) , this . ecipher ) ;
fout = new FileOutputStream ( outFileName ) ;
2005-04-07 15:19:42 -04:00
// write magic and properties of original file
// - we encrypt the original date, the encryption date, the file size, the flag
// and file name together to the string A and calculate the length AL of that string
// - the length of the file name is therefore equal to AL-(17+17+11+1) = AL-46
// - AL is then b64-ed and also encrypted which results into string B
// - the length of B is BL; BL is then b64-ed to a string C of fixed length 1
// - after the magic String we write C, B and A
try {
2012-07-05 04:23:07 -04:00
final String A = UTF8 . String ( this . ecipher . doFinal ( X . getBytes ( " UTF8 " ) ) ) ;
final String B = UTF8 . String ( this . ecipher . doFinal ( Base64Order . standardCoder . encodeLongSB ( A . length ( ) , 2 ) . toString ( ) . getBytes ( " UTF8 " ) ) ) ; // most probable not longer than 4
2011-02-24 19:56:31 -05:00
final String C = Base64Order . standardCoder . encodeLongSB ( B . length ( ) , 1 ) . toString ( ) ; // fixed length 1 (6 bits, that should be enough)
2011-04-12 01:02:36 -04:00
fout . write ( UTF8 . getBytes ( magicString ) ) ; // the magic string, used to identify a 'crypt'-file
fout . write ( UTF8 . getBytes ( C ) ) ;
fout . write ( UTF8 . getBytes ( B ) ) ;
fout . write ( UTF8 . getBytes ( A ) ) ;
2005-04-07 15:19:42 -04:00
// write content of file
copy ( fout , fin , 512 ) ;
}
2008-08-02 08:12:04 -04:00
catch ( final javax . crypto . IllegalBlockSizeException e ) { System . err . println ( " ERROR: " + e . getMessage ( ) ) ; }
catch ( final javax . crypto . BadPaddingException e ) { System . err . println ( " ERROR: " + e . getMessage ( ) ) ; }
} catch ( final FileNotFoundException e ) {
2005-04-07 15:19:42 -04:00
System . err . println ( " ERROR: file ' " + inFileName + " ' not found " ) ;
2008-08-02 08:12:04 -04:00
} catch ( final IOException e ) {
2005-04-07 15:19:42 -04:00
System . err . println ( " ERROR: IO trouble " ) ;
2017-06-02 22:00:46 -04:00
} finally {
try {
if ( fin ! = null ) {
fin . close ( ) ;
}
} catch ( IOException ignored ) {
}
try {
if ( fout ! = null ) {
fout . close ( ) ;
}
} catch ( IOException ignored ) {
}
2005-04-07 15:19:42 -04:00
}
}
2012-07-05 04:23:07 -04:00
2008-08-02 08:12:04 -04:00
public void decryptFile ( final String inFileName , final String outFileName ) {
2005-04-07 15:19:42 -04:00
InputStream fin = null ;
OutputStream fout = null ;
try {
// Start opening the files
fin = new BufferedInputStream ( new FileInputStream ( inFileName ) , 4096 ) ;
// read the file properties
2008-08-13 06:37:53 -04:00
final byte [ ] thisMagic = new byte [ magicString . length ( ) ] ;
fin . read ( thisMagic ) ;
2005-04-07 15:19:42 -04:00
2011-03-07 15:36:40 -05:00
if ( ! ( ( UTF8 . String ( thisMagic ) ) . equals ( magicString ) ) ) {
2005-04-07 15:19:42 -04:00
// this is not an crypt file, so dont do anything
fin . close ( ) ;
return ;
}
2008-08-13 06:37:53 -04:00
final byte [ ] C = new byte [ 1 ] ;
fin . read ( C ) ; // the length of the following String, encoded as b64
2011-03-07 15:36:40 -05:00
final byte [ ] B = new byte [ ( int ) Base64Order . standardCoder . decodeLong ( UTF8 . String ( C ) ) ] ;
2008-08-13 06:37:53 -04:00
fin . read ( B ) ; // this is again the length of the following string, as encrypted b64-ed integer
2012-07-05 04:23:07 -04:00
final byte [ ] A = new byte [ ( int ) Base64Order . standardCoder . decodeLong ( UTF8 . String ( this . dcipher . doFinal ( B ) ) ) ] ;
2008-08-13 06:37:53 -04:00
fin . read ( A ) ;
2012-07-05 04:23:07 -04:00
final String X = UTF8 . String ( this . dcipher . doFinal ( A ) ) ;
2005-04-07 15:19:42 -04:00
System . out . println ( " TEST: detecting X-String : " + X ) ;
// reconstruct the properties
2008-08-02 08:12:04 -04:00
final Date inFileDate = dateFormatter . parse ( X . substring ( 0 , 17 ) , new ParsePosition ( 0 ) ) ;
final Date encryptionDate = dateFormatter . parse ( X . substring ( 17 , 34 ) , new ParsePosition ( 0 ) ) ;
2009-01-30 10:33:00 -05:00
final long inFileSize = Base64Order . standardCoder . decodeLong ( X . substring ( 34 , 45 ) ) ;
2008-08-02 08:12:04 -04:00
final String flag = X . substring ( 45 , 46 ) ;
final String origFileName = X . substring ( 46 ) ;
2005-04-07 15:19:42 -04:00
System . out . println ( " TEST: detecting inFileDate : " + inFileDate ) ;
System . out . println ( " TEST: detecting encryptionDate: " + encryptionDate ) ;
System . out . println ( " TEST: detecting inFileLength : " + inFileSize ) ;
System . out . println ( " TEST: detecting flag : " + flag ) ;
System . out . println ( " TEST: detecting inFileName : " + origFileName ) ;
// open the output file
2012-07-05 04:23:07 -04:00
fout = new BufferedOutputStream ( new CipherOutputStream ( new FileOutputStream ( outFileName ) , this . dcipher ) , 4096 ) ;
2005-04-07 15:19:42 -04:00
// read and decrypt the file
copy ( fout , fin , 512 ) ;
2012-07-05 04:23:07 -04:00
2005-04-07 15:19:42 -04:00
// do postprocessing
2008-08-02 08:12:04 -04:00
} catch ( final BadPaddingException e ) {
2005-04-07 15:19:42 -04:00
System . err . println ( " ERROR: decryption of ' " + inFileName + " ' not possible: " + e . getMessage ( ) ) ;
2008-08-02 08:12:04 -04:00
} catch ( final IllegalBlockSizeException e ) {
2005-04-07 15:19:42 -04:00
System . err . println ( " ERROR: decryption of ' " + inFileName + " ' not possible: " + e . getMessage ( ) ) ;
2008-08-02 08:12:04 -04:00
} catch ( final FileNotFoundException e ) {
2005-04-07 15:19:42 -04:00
System . err . println ( " ERROR: file ' " + inFileName + " ' not found " ) ;
2008-08-02 08:12:04 -04:00
} catch ( final IOException e ) {
2005-04-07 15:19:42 -04:00
System . err . println ( " ERROR: IO trouble " ) ;
2017-06-02 06:14:29 -04:00
} finally {
2008-06-06 12:01:27 -04:00
try { if ( fin ! = null ) {
fin . close ( ) ;
2008-08-02 08:12:04 -04:00
} } catch ( final Exception ee ) { }
2008-06-06 12:01:27 -04:00
try { if ( fout ! = null ) {
fout . close ( ) ;
2008-08-02 08:12:04 -04:00
} } catch ( final Exception ee ) { }
2005-04-07 15:19:42 -04:00
}
}
2012-07-05 04:23:07 -04:00
2008-08-02 08:12:04 -04:00
private static void copy ( final OutputStream out , final InputStream in , final int bufferSize ) throws IOException {
final InputStream bIn = new BufferedInputStream ( in , bufferSize ) ;
final OutputStream bOut = new BufferedOutputStream ( out , bufferSize ) ;
final byte [ ] buf = new byte [ bufferSize ] ;
2005-04-07 15:19:42 -04:00
int n ;
while ( ( n = bIn . read ( buf ) ) > 0 ) bOut . write ( buf , 0 , n ) ;
bIn . close ( ) ;
bOut . close ( ) ;
}
2008-08-02 08:12:04 -04:00
public static String scrambleString ( final String key , final String s ) {
2005-04-07 15:19:42 -04:00
// we perform several operations
// - generate salt
// - gzip string
// - crypt string with key and salt
// - base64-encode result
// - attach salt and return
2008-08-02 08:12:04 -04:00
final String salt = randomSalt ( ) ;
2005-04-07 15:19:42 -04:00
//System.out.println("Salt=" + salt);
2008-08-02 08:12:04 -04:00
final cryptbig c = new cryptbig ( key , salt ) ;
2005-04-07 15:19:42 -04:00
boolean gzFlag = true ;
2020-07-26 17:44:54 -04:00
byte [ ] gz = Gzip . gzipString ( s ) ;
2005-04-07 15:19:42 -04:00
if ( gz . length > s . length ( ) ) {
// revert compression
try {
gz = s . getBytes ( " UTF8 " ) ;
gzFlag = false ;
2008-08-02 08:12:04 -04:00
} catch ( final UnsupportedEncodingException e ) {
2005-04-07 15:19:42 -04:00
return null ;
}
}
//System.out.println("GZIP length=" + gz.length);
if ( gz = = null ) return null ;
2008-08-02 08:12:04 -04:00
final byte [ ] enc = c . encryptArray ( gz ) ;
2005-04-07 15:19:42 -04:00
if ( enc = = null ) return null ;
2009-01-30 10:33:00 -05:00
return salt + ( ( gzFlag ) ? " 1 " : " 0 " ) + Base64Order . enhancedCoder . encode ( enc ) ;
2005-04-07 15:19:42 -04:00
}
2015-08-02 23:37:34 -04:00
public static String descrambleString ( final String key , String s ) {
2008-08-02 08:12:04 -04:00
final String salt = s . substring ( 0 , 8 ) ;
final boolean gzFlag = ( s . charAt ( 8 ) = = '1' ) ;
2005-04-07 15:19:42 -04:00
s = s . substring ( 9 ) ;
2008-08-02 08:12:04 -04:00
final cryptbig c = new cryptbig ( key , salt ) ;
2009-07-06 11:21:43 -04:00
final byte [ ] b64dec = Base64Order . enhancedCoder . decode ( s ) ;
2005-04-07 15:19:42 -04:00
if ( b64dec = = null ) return null ; // error in input string (inconsistency)
2008-08-02 08:12:04 -04:00
final byte [ ] dec = c . decryptArray ( b64dec ) ;
2005-04-07 15:19:42 -04:00
if ( dec = = null ) return null ;
2020-07-26 17:44:54 -04:00
if ( gzFlag ) return Gzip . gunzipString ( dec ) ;
2011-03-07 15:36:40 -05:00
return UTF8 . String ( dec ) ;
2005-04-07 15:19:42 -04:00
}
// --------------------------------------------------------
// Section: simple Codings
// --------------------------------------------------------
2008-08-02 08:12:04 -04:00
public static String simpleEncode ( final String content ) {
2005-04-07 15:19:42 -04:00
return simpleEncode ( content , null , 'b' ) ;
}
2008-08-02 08:12:04 -04:00
public static String simpleEncode ( final String content , final String key ) {
2005-04-07 15:19:42 -04:00
return simpleEncode ( content , key , 'b' ) ;
}
2008-08-02 08:12:04 -04:00
public static String simpleEncode ( final String content , String key , final char method ) {
2005-04-07 15:19:42 -04:00
if ( key = = null ) key = " NULL " ;
if ( method = = 'p' ) return " p| " + content ;
2009-01-30 10:33:00 -05:00
if ( method = = 'b' ) return " b| " + Base64Order . enhancedCoder . encodeString ( content ) ;
2020-07-26 17:44:54 -04:00
if ( method = = 'z' ) return " z| " + Base64Order . enhancedCoder . encode ( Gzip . gzipString ( content ) ) ;
2005-04-07 15:19:42 -04:00
if ( method = = 'c' ) return " c| " + scrambleString ( key , content ) ;
return null ;
}
2015-08-02 23:37:34 -04:00
public static String simpleDecode ( String encoded , final String key ) {
2005-04-07 15:19:42 -04:00
if ( ( encoded = = null ) | | ( encoded . length ( ) < 3 ) ) return null ;
if ( encoded . charAt ( 1 ) ! = '|' ) return encoded ; // not encoded
2008-08-02 08:12:04 -04:00
final char method = encoded . charAt ( 0 ) ;
2005-04-07 15:19:42 -04:00
encoded = encoded . substring ( 2 ) ;
if ( method = = 'p' ) return encoded ;
2009-07-06 11:21:43 -04:00
if ( method = = 'b' ) return Base64Order . enhancedCoder . decodeString ( encoded ) ;
2020-07-26 17:44:54 -04:00
if ( method = = 'z' ) return Gzip . gunzipString ( Base64Order . enhancedCoder . decode ( encoded ) ) ;
2005-04-07 15:19:42 -04:00
if ( method = = 'c' ) return descrambleString ( key , encoded ) ;
return null ;
}
// --------------------------------------------------------
// Section: one-way encryption
// --------------------------------------------------------
2008-08-02 08:12:04 -04:00
public static String oneWayEncryption ( final String key ) {
final cryptbig crypter = new cryptbig ( key ) ;
2005-04-07 15:19:42 -04:00
String e = crypter . encryptString ( key ) ;
2012-07-10 16:59:03 -04:00
if ( e . isEmpty ( ) ) e = " 0XXXX " ;
2008-08-06 15:43:12 -04:00
if ( e . length ( ) % 2 ! = 0 ) e + = " X " ;
2005-04-07 15:19:42 -04:00
while ( e . length ( ) < 32 ) e = e + e ;
2008-08-02 08:12:04 -04:00
final char [ ] r = new char [ 16 ] ;
2005-04-07 15:19:42 -04:00
for ( int i = 0 ; i < 16 ; i + + ) r [ i ] = e . charAt ( 2 * i + 1 ) ;
return new String ( r ) ;
}
// --------------------------------------------------------
// Section: command interface
// --------------------------------------------------------
private static void help ( ) {
System . out . println ( " AnomicCrypt (2003) by Michael Christen " ) ;
System . out . println ( " Password-based encryption using the " + defaultMethod + " -method in standard java " ) ;
System . out . println ( " usage: crypt -h | -help " ) ;
System . out . println ( " crypt -1 <passwd> " ) ;
System . out . println ( " crypt -md5 <file> " ) ;
System . out . println ( " crypt ( -es64 | -ds64 | -ec64 | -dc64 ) <string> " ) ;
System . out . println ( " crypt ( -e | -d ) <key> <string> " ) ;
System . out . println ( " crypt -enc <key> <file> \\ " ) ;
System . out . println ( " [-o <target-file> | -preserveFilename] \\ " ) ;
System . out . println ( " [-d <YYYYMMddHHmmSSsss> | -preserveDate] [-noZip] " ) ;
System . out . println ( " crypt -dec <key> <file> \\ " ) ;
System . out . println ( " [-o <target-file> | -preserveFilename] \\ " ) ;
System . out . println ( " [-d <YYYYMMddHHmmSSsss> | -preserveDate] " ) ;
System . out . println ( " crypt ( -info | -name | -size | -date | -edate ) \\ " ) ;
System . out . println ( " <key> <encrypted-file> " ) ;
}
private static void longhelp ( ) {
// --line-help-- *---------------------------------------------------------------
System . out . println ( " AnomicCrypt (2003) by Michael Christen " ) ;
System . out . println ( " " ) ;
System . out . println ( " " ) ;
System . out . println ( " crypt -1 <passwd> " ) ;
System . out . println ( " " ) ;
System . out . println ( " One-way encryption of the given password. " ) ;
System . out . println ( " The result is computed by encoding the word with the word as " ) ;
System . out . println ( " the password and repeating it until the length is greater " ) ;
System . out . println ( " than 32. Then every second character is taken to compose the " ) ;
System . out . println ( " result which has always the length of 16 characters. " ) ;
System . out . println ( " " ) ;
System . out . println ( " " ) ;
System . out . println ( " crypt -md5 <file> " ) ;
System . out . println ( " " ) ;
System . out . println ( " MD5 digest according to RFC 1321. The resulting bytes are " ) ;
System . out . println ( " encoded as two-digit hex and concatenated to a single string. " ) ;
System . out . println ( " " ) ;
System . out . println ( " " ) ;
System . out . println ( " crypt -ec64 <cardinal> " ) ;
System . out . println ( " " ) ;
System . out . println ( " Encoding of a cardianal (a positive long integer) with the " ) ;
System . out . println ( " built-in non-standard base-64 algorithm. " ) ;
System . out . println ( " " ) ;
System . out . println ( " " ) ;
System . out . println ( " crypt -dc64 <string> " ) ;
System . out . println ( " " ) ;
System . out . println ( " Decoding of the given b64-coded string to a cardinal number. " ) ;
System . out . println ( " " ) ;
System . out . println ( " " ) ;
System . out . println ( " crypt -es64 <string> " ) ;
System . out . println ( " " ) ;
System . out . println ( " Encoding of a given String to a b64 string. " ) ;
System . out . println ( " " ) ;
System . out . println ( " " ) ;
System . out . println ( " crypt -ds64 <string> " ) ;
System . out . println ( " " ) ;
System . out . println ( " Decoding of a given b64-coded string to a normal string. " ) ;
System . out . println ( " " ) ;
System . out . println ( " " ) ;
System . out . println ( " crypt -e <key> <string> " ) ;
System . out . println ( " " ) ;
System . out . println ( " Encryption of a given Unicode-String. " ) ;
System . out . println ( " The given string is first encoded to an UTF-8 byte stream, then " ) ;
System . out . println ( " encoded using a password based encryption and then finaly " ) ;
System . out . println ( " encoded to b64 to generate a printable form. " ) ;
System . out . println ( " The PBE method is " + defaultMethod + " . " ) ;
System . out . println ( " " ) ;
System . out . println ( " " ) ;
System . out . println ( " crypt -d <key> <string> " ) ;
System . out . println ( " " ) ;
System . out . println ( " Decryption of a string. " ) ;
System . out . println ( " The string is b64-decoded, " + defaultMethod + " -decrypted, " ) ;
System . out . println ( " and then transformed to an unicode string. " ) ;
System . out . println ( " " ) ;
System . out . println ( " " ) ;
System . out . println ( " crypt -enc <key> <file> \\ " ) ;
System . out . println ( " [-o <target-file> | -preserveFilename] \\ " ) ;
System . out . println ( " [-d <target-date YYYYMMddHHmmSSsss> | -preserveDate] [-noZip] " ) ;
System . out . println ( " " ) ;
System . out . println ( " " ) ;
System . out . println ( " " ) ;
System . out . println ( " " ) ;
System . out . println ( " crypt -dec <key> <file> \\ " ) ;
System . out . println ( " [-o <target-file> | -preserveFilename] \\ " ) ;
System . out . println ( " [-d <target-date YYYYMMddHHmmSSsss> | -preserveDate] " ) ;
System . out . println ( " " ) ;
System . out . println ( " " ) ;
System . out . println ( " crypt ( -info | -name | -size | -date | -edate ) <key> <encrypted-file> " ) ;
System . out . println ( " " ) ;
System . out . println ( " " ) ;
}
2008-08-02 08:12:04 -04:00
public static void main ( final String [ ] s ) {
2005-04-07 15:19:42 -04:00
if ( s . length = = 0 ) {
help ( ) ;
System . exit ( 0 ) ;
}
if ( ( s [ 0 ] . equals ( " -h " ) ) | | ( s [ 0 ] . equals ( " -help " ) ) ) {
longhelp ( ) ;
System . exit ( 0 ) ;
}
if ( s [ 0 ] . equals ( " -tc " ) ) {
// list all available crypt mehtods:
2008-08-02 08:12:04 -04:00
final Set < String > methods = listCryptoMethods ( " Cipher " ) ;
2005-04-07 15:19:42 -04:00
System . out . println ( methods . size ( ) + " crypt methods: " + methods . toString ( ) ) ;
testCryptMethods ( methods ) ;
System . exit ( 0 ) ;
}
if ( s [ 0 ] . equals ( " -random " ) ) {
2008-08-02 08:12:04 -04:00
final int count = ( ( s . length = = 2 ) ? ( Integer . parseInt ( s [ 1 ] ) ) : 1 ) ;
2005-04-07 15:19:42 -04:00
for ( int i = 0 ; i < count ; i + + ) System . out . println ( randomSalt ( ) ) ;
System . exit ( 0 ) ;
}
if ( s [ 0 ] . equals ( " -1 " ) ) {
if ( s . length ! = 2 ) { help ( ) ; System . exit ( - 1 ) ; }
System . out . println ( oneWayEncryption ( s [ 1 ] ) ) ;
System . exit ( 0 ) ;
}
if ( s [ 0 ] . equals ( " -ec64 " ) ) {
// generate a b64 encoding from a given cardinal
if ( s . length ! = 2 ) { help ( ) ; System . exit ( - 1 ) ; }
2011-02-24 19:56:31 -05:00
System . out . println ( Base64Order . standardCoder . encodeLongSB ( Long . parseLong ( s [ 1 ] ) , 0 ) . toString ( ) ) ;
2005-04-07 15:19:42 -04:00
System . exit ( 0 ) ;
}
if ( s [ 0 ] . equals ( " -dc64 " ) ) {
// generate a b64 decoding from a given cardinal
if ( s . length ! = 2 ) { help ( ) ; System . exit ( - 1 ) ; }
2009-01-30 10:33:00 -05:00
System . out . println ( Base64Order . standardCoder . decodeLong ( s [ 1 ] ) ) ;
2005-04-07 15:19:42 -04:00
System . exit ( 0 ) ;
}
if ( s [ 0 ] . equals ( " -es64 " ) ) {
// generate a b64 encoding from a given string
if ( s . length ! = 2 ) { help ( ) ; System . exit ( - 1 ) ; }
2009-01-30 10:33:00 -05:00
System . out . println ( Base64Order . standardCoder . encodeString ( s [ 1 ] ) ) ;
2005-04-07 15:19:42 -04:00
System . exit ( 0 ) ;
}
if ( s [ 0 ] . equals ( " -ds64 " ) ) {
// generate a b64 decoding from a given string
if ( s . length ! = 2 ) { help ( ) ; System . exit ( - 1 ) ; }
2009-07-06 11:21:43 -04:00
System . out . println ( Base64Order . standardCoder . decodeString ( s [ 1 ] ) ) ;
2005-04-07 15:19:42 -04:00
System . exit ( 0 ) ;
}
if ( s [ 0 ] . equals ( " -ess " ) ) {
// 'scramble' string
if ( s . length ! = 3 ) { help ( ) ; System . exit ( - 1 ) ; }
2008-08-02 08:12:04 -04:00
final long t = System . currentTimeMillis ( ) ;
2005-04-07 15:19:42 -04:00
System . out . println ( scrambleString ( s [ 1 ] , s [ 2 ] ) ) ;
System . out . println ( " Calculation time: " + ( System . currentTimeMillis ( ) - t ) + " milliseconds " ) ;
System . exit ( 0 ) ;
}
if ( s [ 0 ] . equals ( " -dss " ) ) {
// 'descramble' string
if ( s . length ! = 3 ) { help ( ) ; System . exit ( - 1 ) ; }
2008-08-02 08:12:04 -04:00
final long t = System . currentTimeMillis ( ) ;
2015-08-02 23:37:34 -04:00
System . out . println ( descrambleString ( s [ 1 ] , s [ 2 ] ) ) ;
2005-04-07 15:19:42 -04:00
System . out . println ( " Calculation time: " + ( System . currentTimeMillis ( ) - t ) + " milliseconds " ) ;
System . exit ( 0 ) ;
}
if ( s [ 0 ] . equals ( " -e " ) ) {
if ( s . length ! = 3 ) { help ( ) ; System . exit ( - 1 ) ; }
System . out . println ( ( new cryptbig ( s [ 1 ] ) ) . encryptString ( s [ 2 ] ) ) ;
System . exit ( 0 ) ;
}
if ( s [ 0 ] . equals ( " -d " ) ) {
if ( s . length ! = 3 ) { help ( ) ; System . exit ( - 1 ) ; }
System . out . println ( ( new cryptbig ( s [ 1 ] ) ) . decryptString ( s [ 2 ] ) ) ;
System . exit ( 0 ) ;
}
if ( s [ 0 ] . equals ( " -md5 " ) ) {
// generate a public key from a password that can be used for encryption
if ( s . length ! = 2 ) { help ( ) ; System . exit ( - 1 ) ; }
2011-02-23 18:04:05 -05:00
String md5s = " " ;
try {
md5s = Digest . encodeMD5Hex ( new File ( s [ 1 ] ) ) ;
2013-07-17 12:31:30 -04:00
} catch ( final IOException e ) {
2011-02-23 18:04:05 -05:00
e . printStackTrace ( ) ;
}
2005-04-07 15:19:42 -04:00
System . out . println ( md5s ) ;
System . exit ( 0 ) ;
}
if ( s [ 0 ] . equals ( " -enc " ) ) {
if ( ( s . length < 3 ) | | ( s . length > 4 ) ) { help ( ) ; System . exit ( - 1 ) ; }
String target ;
if ( s . length = = 3 ) target = s [ 2 ] + " .crypt " ; else target = s [ 3 ] ;
2012-07-05 04:23:07 -04:00
( new cryptbig ( s [ 1 ] ) ) . encryptFile ( s [ 2 ] , target ) ;
2005-04-07 15:19:42 -04:00
System . exit ( 0 ) ;
}
if ( s [ 0 ] . equals ( " -dec " ) ) {
if ( ( s . length < 3 ) | | ( s . length > 4 ) ) { help ( ) ; System . exit ( - 1 ) ; }
String target ;
if ( s . length = = 3 ) {
if ( s [ 2 ] . endsWith ( " .crypt " ) )
target = s [ 2 ] . substring ( 0 , s [ 2 ] . length ( ) - 7 ) ;
else
target = s [ 2 ] + " .decoded " ;
} else {
target = s [ 3 ] ;
}
( new cryptbig ( s [ 1 ] ) ) . decryptFile ( s [ 2 ] , target ) ;
System . exit ( 0 ) ;
}
help ( ) ; System . exit ( - 1 ) ;
}
}