/****************************************************************************** * * swcipher.cpp - code for class 'SWCipher'- a driver class that * provides cipher utilities * * $Id: swcipher.cpp 3755 2020-07-19 18:43:07Z scribe $ * * Copyright 1999-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society * P. O. Box 2528 * Tempe, AZ 85280-2528 * * 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 version 2. * * 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. * */ package org.crosswire.sword.modules.common; import java.util.Map; import java.util.HashMap; import java.io.BufferedReader; import java.io.InputStreamReader; class SWCipher { static class Sapphire { private String cipherKey; private int size; public void initialize(String cipherKey, int size) { this.cipherKey = cipherKey; this.size = size; } public char encrypt(char ch) { return ch; } public char decrypt(char ch) { return ch; } } private static final char lats[]; static { lats = new char[]{ 'b', 'c', 'e', 'a', 'f', 'g', 'i', 'j', 'k', 'l', 'h', 'm', 'p', 'q', 'B', 'r', 'H', 'o', 's', 't', 'T', 'u', 'w', 'x', 'y', 'A', 'd', 'C', 'D', 'z', 'E', 'F', 'I', 'J', 'K', 'G', 'L', 'N', 'O', '7', 'P', 'Q', 'M', 'R', 'S', 'U', 'V', 'W', 'X', 'Y', '9', '0', '1', '2', 'Z', '3', '6', '4', 'n', '8', 'v', '5' }; } private Sapphire master; private Sapphire work; private StringBuffer buf; private boolean cipher; private int len; /****************************************************************************** * SWCipher Constructor - Initializes data for instance of SWCipher * */ SWCipher(String key) { String cipherKey = personalize(key, false); master.initialize(cipherKey, cipherKey.length()); buf = null; } void setUncipheredBuf(String ibuf, int ilen) { if (ibuf != null) { if (ilen == 0) { len = ibuf.length(); ilen = len + 1; } else len = ilen; buf = new StringBuffer(); buf.append(ibuf, 0, ilen); cipher = false; } decode(); } String getUncipheredBuf() { decode(); return buf.toString(); } int setCipheredBuf(int ilen, String ibuf) { if (ibuf != null) { buf = new StringBuffer(); buf.append(ibuf, 0, ilen); len = ilen; cipher = true; } encode(); return len; } String getCipheredBuf(int ilen) { encode(); return buf.toString(); } /****************************************************************************** * SWCipher::encode - This function "encodes" the input stream into the * output stream. * The GetChars() and SendChars() functions are * used to separate this method from the actual * i/o. */ void encode() { if (!cipher) { work = master; for (int i = 0; i < len; i++) buf.setCharAt(i, work.encrypt(buf.charAt(i))); cipher = true; } } /****************************************************************************** * SWCipher::decode - This function "decodes" the input stream into the * output stream. * The GetChars() and SendChars() functions are * used to separate this method from the actual * i/o. */ void decode() { if (cipher) { work = master; int i; for (i = 0; i < len; i++) buf.setCharAt(i, work.decrypt(buf.charAt(i))); buf.setLength(i); cipher = false; } } /****************************************************************************** * SWCipher::setCipherKey - setter for a new CipherKey * */ void setCipherKey(String ikey) { String cipherKey = personalize(ikey, false); master.initialize(cipherKey, cipherKey.length()); } /****************************************************************************** * SWCipher::personalize - a simple personalization encoding * * encode - whether to encode or decode * */ public static String personalize(String buf, boolean encode) { Map charHash = new HashMap(); for (int i = 0; i < 62; ++i) charHash.put(lats[i], i); StringBuffer[] segs = new StringBuffer[5]; for (int i = 0; i < 5; ++i) segs[i] = new StringBuffer(); int segn = 0; for (int i = 0; i < buf.length() && segn < 5; ++i) { if (buf.charAt(i) == '-') ++segn; else segs[segn].append(buf.charAt(i)); } String result = ""; String chkSum = segs[4].toString(); if (segs[4].length() < 5) segs[4].setLength(4); // just be sure we don't ever charAt(x) where x > length for (int i = 0; i < 4; ++i) { int csum = 0; for (int j = 0; j < segs[i].length() && j < segs[0].length(); ++j) { int hash = charHash.get(segs[i].charAt(j)); int obfusHash = charHash.get(segs[0].charAt(j%segs[0].length())); if (encode) { obfusHash = hash - (i != 0 ? obfusHash : 0); if (obfusHash < 0) obfusHash = (62 + obfusHash); } else { obfusHash = hash + (i != 0 ? obfusHash : 0); obfusHash %= 62; } if (i != 0) segs[i].setCharAt(j, lats[obfusHash]); csum += (encode ? obfusHash : hash); } segs[4].setCharAt(i, lats[csum%62]); if (result.length() != 0) result += "-"; result += (!encode && i == 0 ? "" : segs[i].toString()); } if (encode) { result += "-"; result += segs[4]; } return (!encode && !chkSum.equals(segs[4].toString().trim())) ? buf : result; } public static void main(String[] argv) { if (argv.length != 2) { System.err.println("usage: SWCipher <0-encipher|1-decipher|2-personalize|3-de-personalize>\n"); return; } int encipher = Integer.parseInt(argv[1]); /* SWFilter *filter = new CipherFilter(argv[0]); */ BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); String text = ""; // Reading data using readLine try { text = reader.readLine(); } catch (Exception e) { e.printStackTrace(); } switch (encipher) { case 2: case 3: text = SWCipher.personalize(text, encipher == 2); break; default: // filter->processText(text, (SWKey *)encipher); } System.out.println(text); } }