001/*
002 *  $URL: $
003 *  $Author: $
004 *  $Revision: $
005 *  $Date: $
006 */
007/*
008 *
009 *  Written by Tom Gutwin - WebARTS Design.
010 *  Copyright (C) 2018 WebARTS Design, North Vancouver Canada
011 *  http://www.webarts.bc.ca
012 *
013 *  This program is free software; you can redistribute it and/or modify
014 *  it under the terms of the GNU General Public License as published by
015 *  the Free Software Foundation; either version 2 of the License, or
016 *  (at your option) any later version.
017 *
018 *  This program is distributed in the hope that it will be useful,
019 *  but WITHOUT ANY WARRANTY; without_ even the implied warranty of
020 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
021 *  GNU General Public License for more details.
022 *
023 *  You should have received a copy of the GNU General Public License
024 *  along with this program; if not, write to the Free Software
025 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
026 */
027package ca.bc.webarts.tools;
028
029import java.io.IOException;
030import java.security.GeneralSecurityException;
031import java.security.NoSuchAlgorithmException;
032import java.util.Base64;
033
034import javax.crypto.Cipher;
035import javax.crypto.KeyGenerator;
036import javax.crypto.SecretKey;
037import javax.crypto.spec.IvParameterSpec;
038import javax.crypto.spec.SecretKeySpec;
039
040import javax.xml.bind.DatatypeConverter;
041import com.aftexsw.util.bzip.BZip;
042
043/**
044 * A simple application that encrypts Strings with AES. It does it completely in-memory, no file caching.
045   * You can also pass it a AES password/SecretKey as a -d option when decrypting.
046   *
047   *
048   **/
049public class StringCrypter extends TomsCrypter
050{
051  /**  A holder for this clients System File Separator.  */
052  public final static String SYSTEM_FILE_SEPERATOR = java.io.File.separator;
053
054  /**  A holder for this clients System line termination separator.  */
055  public final static String SYSTEM_LINE_SEPERATOR =
056                                           System.getProperty("line.separator");
057  private static final String APPLICATION_NAME = "WebARTSDesign-StringCrypter/0.2";
058
059  private static SecretKey secretKey = null;
060  private static Cipher cipher = null;
061
062
063  public  StringCrypter() throws GeneralSecurityException, IOException
064  {
065    super();
066  }
067
068
069  /**
070  * Syntax:<br />
071  * java ca.bc.webarts.tools.StringCrypter [-0 | -1] [-d passwordKey] StringToCrypt<br />
072  * <br />
073  **/
074  public static void main(String[] args)
075  {
076    boolean encrypting = false;
077    String str = "";
078    int encMode = 0; // default is to use this class impl
079    if (args!=null && args.length>0)
080    try
081    {
082      StringCrypter instance = new StringCrypter();
083      if (args.length>0)
084      {
085        if(args[0].equals("-d") && args.length>2)
086        {
087          secretKey = instance.decodeBase64ToAESKey(args[1]);
088          for (int i=2; i<args.length; i++)
089            str += args[i] +" ";
090          str=str.trim();
091          System.out.println("Decrypting: "+str);
092          if(encMode==0)
093            System.out.println(instance.aesDecrypt(str));
094          else if (encMode==1)
095            System.out.println(instance.decryptString(str));
096        }
097        else if(args.length>1 && (args[0].equals("-0") || args[0].equals("-1")))
098        {
099          if(args[0].equals("-1")) encMode = 1;
100          for (int i=1; i<args.length; i++)
101            str += args[i] +" ";
102          str=str.trim();
103          System.out.println("Encrypting: "+str);
104          if(encMode==0)
105          {
106            String enCrypted = instance.aesEncrypt(str);
107            System.out.println(enCrypted);
108            System.out.println("Test Decrypt: "+instance.aesDecrypt(enCrypted));
109          }
110          else if (encMode==1)
111          {
112            String enCrypted = instance.encryptString(str);
113            System.out.println(enCrypted);
114            System.out.println("Test Decrypt: "+instance.decryptString(enCrypted));
115          }
116        }
117        else
118        {
119          for (int i=0; i<args.length; i++)
120            str += args[i] +" ";
121          str=str.trim();
122          System.out.println("Encrypting: "+str);
123          if(encMode==0)
124          {
125            String enCrypted = instance.aesEncrypt(str);
126            System.out.println(enCrypted);
127            System.out.println("encodedPasswordKey= "+ instance.encodeAESKeyToBase64(instance.getAESSecretKey()));
128            System.out.println("Test Decrypt: "+instance.aesDecrypt(enCrypted));
129          }
130          else if (encMode==1)
131          {
132            String enCrypted = instance.encryptString(str);
133            System.out.println(enCrypted);
134            System.out.println("Test Decrypt: "+instance.decryptString(enCrypted));
135          }
136        }
137      }
138      else
139      {
140        System.out.println("You gotta give me a String.");
141      }
142    }
143    catch (Exception ex)
144       {
145        System.out.println("Gag.");
146        ex.printStackTrace();
147      }
148  }
149
150
151  /** from https://javapapers.com/java/java-symmetric-aes-encryption-decryption-using-jce . **/
152  public  String aesEncrypt(String plainText)   throws Exception
153  {
154    byte[] plainTextByte = plainText.getBytes();
155    cipher = Cipher.getInstance("AES");
156    cipher.init(Cipher.ENCRYPT_MODE, getAESSecretKey());
157    byte[] encryptedByte = cipher.doFinal(plainTextByte);
158    java.util.Base64.Encoder encoder = java.util.Base64.getEncoder();
159    String encryptedText = encoder.encodeToString(encryptedByte);
160    return encryptedText;
161  }
162
163
164  /** from https://javapapers.com/java/java-symmetric-aes-encryption-decryption-using-jce . **/
165  public  String aesDecrypt(String encryptedText) throws Exception
166  {
167    java.util.Base64.Decoder decoder = java.util.Base64.getDecoder();
168    byte[] encryptedTextByte = decoder.decode(encryptedText);
169    cipher = Cipher.getInstance("AES");
170    cipher.init(Cipher.DECRYPT_MODE, getAESSecretKey());
171    byte[] decryptedByte = cipher.doFinal(encryptedTextByte);
172    String decryptedText = new String(decryptedByte);
173    return decryptedText;
174  }
175
176
177  private SecretKey getAESSecretKey(){ return generateAESSecretKey(false);}
178  private SecretKey generateAESSecretKey(boolean createNew)
179  {
180    //System.out.println("Secret AES Key == null?"+(secretKey==null));
181
182    if(secretKey==null || createNew)
183    {
184      //System.out.println("Generating Secret AES Key");
185      try
186      {
187        KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
188        //cipher = Cipher.getInstance("AES");
189        keyGenerator.init(128);
190        secretKey = keyGenerator.generateKey();
191      } catch (Exception ex) {
192          ex.printStackTrace();
193      }
194    }
195    //System.out.println("Secret AES Key == null?"+(secretKey==null));
196    return secretKey;
197  }
198
199}