0001: /**
0002: * $RCSfile$
0003: * $Revision: 3657 $
0004: * $Date: 2002-09-09 08:31:31 -0700 (Mon, 09 Sep 2002) $
0005: *
0006: * Adapted from Markus Hahn's Blowfish package so that all functionality is
0007: * in a single source file. Please visit the following URL for his excellent
0008: * package: http://www.hotpixel.net/software.html
0009: *
0010: * Copyright (c) 1997-2002 Markus Hahn <markus_hahn@gmx.net>
0011: *
0012: * Released under the Apache 2.0 license.
0013: */package org.jivesoftware.util;
0014:
0015: import java.security.MessageDigest;
0016: import java.util.Random;
0017:
0018: /**
0019: * A class that provides easy Blowfish encryption.<p>
0020: *
0021: * @author Markus Hahn <markus_hahn@gmx.net>
0022: * @author Gaston Dombiak
0023: */
0024: public class Blowfish {
0025:
0026: private BlowfishCBC m_bfish;
0027: private static Random m_rndGen = new Random();
0028:
0029: /**
0030: * Creates a new Blowfish object using the specified key (oversized
0031: * password will be cut).
0032: *
0033: * @param password the password (treated as a real unicode array)
0034: */
0035: public Blowfish(String password) {
0036: // hash down the password to a 160bit key
0037: MessageDigest digest = null;
0038: try {
0039: digest = MessageDigest.getInstance("SHA1");
0040: digest.update(password.getBytes());
0041: } catch (Exception e) {
0042: Log.error(e);
0043: }
0044:
0045: // setup the encryptor (use a dummy IV)
0046: m_bfish = new BlowfishCBC(digest.digest(), 0);
0047: digest.reset();
0048: }
0049:
0050: /**
0051: * Encrypts a string (treated in UNICODE) using the
0052: * standard Java random generator, which isn't that
0053: * great for creating IVs
0054: *
0055: * @param sPlainText string to encrypt
0056: * @return encrypted string in binhex format
0057: */
0058: public String encryptString(String sPlainText) {
0059: // get the IV
0060: long lCBCIV;
0061: synchronized (m_rndGen) {
0062: lCBCIV = m_rndGen.nextLong();
0063: }
0064:
0065: // map the call;
0066: return encStr(sPlainText, lCBCIV);
0067: }
0068:
0069: // Internal routine for string encryption
0070:
0071: private String encStr(String sPlainText, long lNewCBCIV) {
0072: // allocate the buffer (align to the next 8 byte border plus padding)
0073: int nStrLen = sPlainText.length();
0074: byte[] buf = new byte[((nStrLen << 1) & 0xfffffff8) + 8];
0075:
0076: // copy all bytes of the string into the buffer (use network byte order)
0077: int nI;
0078: int nPos = 0;
0079: for (nI = 0; nI < nStrLen; nI++) {
0080: char cActChar = sPlainText.charAt(nI);
0081: buf[nPos++] = (byte) ((cActChar >> 8) & 0x0ff);
0082: buf[nPos++] = (byte) (cActChar & 0x0ff);
0083: }
0084:
0085: // pad the rest with the PKCS5 scheme
0086: byte bPadVal = (byte) (buf.length - (nStrLen << 1));
0087: while (nPos < buf.length) {
0088: buf[nPos++] = bPadVal;
0089: }
0090:
0091: synchronized (m_bfish) {
0092: // create the encryptor
0093: m_bfish.setCBCIV(lNewCBCIV);
0094:
0095: // encrypt the buffer
0096: m_bfish.encrypt(buf);
0097: }
0098:
0099: // return the binhex string
0100: byte[] newCBCIV = new byte[BlowfishCBC.BLOCKSIZE];
0101: longToByteArray(lNewCBCIV, newCBCIV, 0);
0102:
0103: return bytesToBinHex(newCBCIV, 0, BlowfishCBC.BLOCKSIZE)
0104: + bytesToBinHex(buf, 0, buf.length);
0105: }
0106:
0107: /**
0108: * decrypts a hexbin string (handling is case sensitive)
0109: * @param sCipherText hexbin string to decrypt
0110: * @return decrypted string (null equals an error)
0111: */
0112: public String decryptString(String sCipherText) {
0113: // get the number of estimated bytes in the string (cut off broken blocks)
0114: int nLen = (sCipherText.length() >> 1) & ~7;
0115:
0116: // does the given stuff make sense (at least the CBC IV)?
0117: if (nLen < BlowfishECB.BLOCKSIZE)
0118: return null;
0119:
0120: // get the CBC IV
0121: byte[] cbciv = new byte[BlowfishCBC.BLOCKSIZE];
0122: int nNumOfBytes = binHexToBytes(sCipherText, cbciv, 0, 0,
0123: BlowfishCBC.BLOCKSIZE);
0124: if (nNumOfBytes < BlowfishCBC.BLOCKSIZE)
0125: return null;
0126:
0127: // something left to decrypt?
0128: nLen -= BlowfishCBC.BLOCKSIZE;
0129: if (nLen == 0) {
0130: return "";
0131: }
0132:
0133: // get all data bytes now
0134: byte[] buf = new byte[nLen];
0135:
0136: nNumOfBytes = binHexToBytes(sCipherText, buf,
0137: BlowfishCBC.BLOCKSIZE * 2, 0, nLen);
0138:
0139: // we cannot accept broken binhex sequences due to padding
0140: // and decryption
0141: if (nNumOfBytes < nLen) {
0142: return null;
0143: }
0144:
0145: synchronized (m_bfish) {
0146: // (got it)
0147: m_bfish.setCBCIV(cbciv);
0148:
0149: // decrypt the buffer
0150: m_bfish.decrypt(buf);
0151: }
0152:
0153: // get the last padding byte
0154: int nPadByte = (int) buf[buf.length - 1] & 0x0ff;
0155:
0156: // ( try to get all information if the padding doesn't seem to be correct)
0157: if ((nPadByte > 8) || (nPadByte < 0)) {
0158: nPadByte = 0;
0159: }
0160:
0161: // calculate the real size of this message
0162: nNumOfBytes -= nPadByte;
0163: if (nNumOfBytes < 0) {
0164: return "";
0165: }
0166:
0167: // success
0168: return byteArrayToUNCString(buf, 0, nNumOfBytes);
0169: }
0170:
0171: /**
0172: * destroys (clears) the encryption engine,
0173: * after that the instance is not valid anymore
0174: */
0175: public void destroy() {
0176: m_bfish.cleanUp();
0177: }
0178:
0179: /**
0180: * implementation of the Blowfish encryption algorithm in ECB mode
0181: * @author Markus Hahn <markus_hahn@gmx.net>
0182: * @version Feburary 14, 2001
0183: */
0184: private static class BlowfishECB {
0185: /** maximum possible key length */
0186: public final static int MAXKEYLENGTH = 56;
0187:
0188: /** block size of this cipher (in bytes) */
0189: public final static int BLOCKSIZE = 8;
0190:
0191: // size of the single boxes
0192: final static int PBOX_ENTRIES = 18;
0193: final static int SBOX_ENTRIES = 256;
0194:
0195: // the boxes
0196: int[] m_pbox;
0197: int[] m_sbox1;
0198: int[] m_sbox2;
0199: int[] m_sbox3;
0200: int[] m_sbox4;
0201:
0202: /**
0203: * default constructor
0204: * @param bfkey key material, up to MAXKEYLENGTH bytes
0205: */
0206: public BlowfishECB(byte[] bfkey) {
0207: // create the boxes
0208: int nI;
0209:
0210: m_pbox = new int[PBOX_ENTRIES];
0211:
0212: for (nI = 0; nI < PBOX_ENTRIES; nI++) {
0213: m_pbox[nI] = pbox_init[nI];
0214: }
0215:
0216: m_sbox1 = new int[SBOX_ENTRIES];
0217: m_sbox2 = new int[SBOX_ENTRIES];
0218: m_sbox3 = new int[SBOX_ENTRIES];
0219: m_sbox4 = new int[SBOX_ENTRIES];
0220:
0221: for (nI = 0; nI < SBOX_ENTRIES; nI++) {
0222: m_sbox1[nI] = sbox_init_1[nI];
0223: m_sbox2[nI] = sbox_init_2[nI];
0224: m_sbox3[nI] = sbox_init_3[nI];
0225: m_sbox4[nI] = sbox_init_4[nI];
0226: }
0227:
0228: // xor the key over the p-boxes
0229:
0230: int nLen = bfkey.length;
0231: if (nLen == 0)
0232: return; // such a setup is also valid (zero key "encryption" is possible)
0233: int nKeyPos = 0;
0234: int nBuild = 0;
0235: int nJ;
0236:
0237: for (nI = 0; nI < PBOX_ENTRIES; nI++) {
0238: for (nJ = 0; nJ < 4; nJ++) {
0239: nBuild = (nBuild << 8)
0240: | (((int) bfkey[nKeyPos]) & 0x0ff);
0241:
0242: if (++nKeyPos == nLen) {
0243: nKeyPos = 0;
0244: }
0245: }
0246: m_pbox[nI] ^= nBuild;
0247: }
0248:
0249: // encrypt all boxes with the all zero string
0250: long lZero = 0;
0251:
0252: // (same as above)
0253: for (nI = 0; nI < PBOX_ENTRIES; nI += 2) {
0254: lZero = encryptBlock(lZero);
0255: m_pbox[nI] = (int) (lZero >>> 32);
0256: m_pbox[nI + 1] = (int) (lZero & 0x0ffffffffL);
0257: }
0258: for (nI = 0; nI < SBOX_ENTRIES; nI += 2) {
0259: lZero = encryptBlock(lZero);
0260: m_sbox1[nI] = (int) (lZero >>> 32);
0261: m_sbox1[nI + 1] = (int) (lZero & 0x0ffffffffL);
0262: }
0263: for (nI = 0; nI < SBOX_ENTRIES; nI += 2) {
0264: lZero = encryptBlock(lZero);
0265: m_sbox2[nI] = (int) (lZero >>> 32);
0266: m_sbox2[nI + 1] = (int) (lZero & 0x0ffffffffL);
0267: }
0268: for (nI = 0; nI < SBOX_ENTRIES; nI += 2) {
0269: lZero = encryptBlock(lZero);
0270: m_sbox3[nI] = (int) (lZero >>> 32);
0271: m_sbox3[nI + 1] = (int) (lZero & 0x0ffffffffL);
0272: }
0273: for (nI = 0; nI < SBOX_ENTRIES; nI += 2) {
0274: lZero = encryptBlock(lZero);
0275: m_sbox4[nI] = (int) (lZero >>> 32);
0276: m_sbox4[nI + 1] = (int) (lZero & 0x0ffffffffL);
0277: }
0278: }
0279:
0280: /**
0281: * to clear data in the boxes before an instance is freed
0282: */
0283: public void cleanUp() {
0284: int nI;
0285:
0286: for (nI = 0; nI < PBOX_ENTRIES; nI++) {
0287: m_pbox[nI] = 0;
0288: }
0289:
0290: for (nI = 0; nI < SBOX_ENTRIES; nI++) {
0291: m_sbox1[nI] = m_sbox2[nI] = m_sbox3[nI] = m_sbox4[nI] = 0;
0292: }
0293: }
0294:
0295: /**
0296: * selftest routine, to check e.g. for a valid class file transmission
0297: * @return true: selftest passed / false: selftest failed
0298: */
0299: public static boolean selfTest() {
0300: // test vector #1 (checking for the "signed bug")
0301: byte[] testKey1 = { (byte) 0x1c, (byte) 0x58, (byte) 0x7f,
0302: (byte) 0x1c, (byte) 0x13, (byte) 0x92, (byte) 0x4f,
0303: (byte) 0xef };
0304: int[] tv_p1 = { 0x30553228, 0x6d6f295a };
0305: int[] tv_c1 = { 0x55cb3774, 0xd13ef201 };
0306: int[] tv_t1 = new int[2];
0307:
0308: // test vector #2 (offical vector by Bruce Schneier)
0309: String sTestKey2 = "Who is John Galt?";
0310: byte[] testKey2 = sTestKey2.getBytes();
0311:
0312: int[] tv_p2 = { 0xfedcba98, 0x76543210 };
0313: int[] tv_c2 = { 0xcc91732b, 0x8022f684 };
0314: int[] tv_t2 = new int[2];
0315:
0316: // start the tests, check for a proper decryption, too
0317:
0318: BlowfishECB testbf1 = new BlowfishECB(testKey1);
0319:
0320: testbf1.encrypt(tv_p1, tv_t1);
0321:
0322: if ((tv_t1[0] != tv_c1[0]) || (tv_t1[1] != tv_c1[1])) {
0323: return false;
0324: }
0325:
0326: testbf1.decrypt(tv_t1);
0327:
0328: if ((tv_t1[0] != tv_p1[0]) || (tv_t1[1] != tv_p1[1])) {
0329: return false;
0330: }
0331:
0332: BlowfishECB testbf2 = new BlowfishECB(testKey2);
0333:
0334: testbf2.encrypt(tv_p2, tv_t2);
0335:
0336: if ((tv_t2[0] != tv_c2[0]) || (tv_t2[1] != tv_c2[1])) {
0337: return false;
0338: }
0339:
0340: testbf2.decrypt(tv_t2);
0341:
0342: if ((tv_t2[0] != tv_p2[0]) || (tv_t2[1] != tv_p2[1])) {
0343: return false;
0344: }
0345:
0346: // all tests passed
0347: return true;
0348: }
0349:
0350: // internal routine to encrypt a 64bit block
0351: protected long encryptBlock(long lPlainBlock) {
0352: // split the block in two 32 bit halves
0353:
0354: int nHi = longHi32(lPlainBlock);
0355: int nLo = longLo32(lPlainBlock);
0356:
0357: // encrypt the block, gain more speed by unrooling the loop
0358: // (we avoid swapping by using nHi and nLo alternating at
0359: // odd an even loop nubers) and using local references
0360:
0361: int[] sbox1 = m_sbox1;
0362: int[] sbox2 = m_sbox2;
0363: int[] sbox3 = m_sbox3;
0364: int[] sbox4 = m_sbox4;
0365:
0366: int[] pbox = m_pbox;
0367:
0368: nHi ^= pbox[0];
0369: nLo ^= (((sbox1[nHi >>> 24] + sbox2[(nHi >>> 16) & 0x0ff]) ^ sbox3[(nHi >>> 8) & 0x0ff]) + sbox4[nHi & 0x0ff])
0370: ^ pbox[1];
0371: nHi ^= (((sbox1[nLo >>> 24] + sbox2[(nLo >>> 16) & 0x0ff]) ^ sbox3[(nLo >>> 8) & 0x0ff]) + sbox4[nLo & 0x0ff])
0372: ^ pbox[2];
0373: nLo ^= (((sbox1[nHi >>> 24] + sbox2[(nHi >>> 16) & 0x0ff]) ^ sbox3[(nHi >>> 8) & 0x0ff]) + sbox4[nHi & 0x0ff])
0374: ^ pbox[3];
0375: nHi ^= (((sbox1[nLo >>> 24] + sbox2[(nLo >>> 16) & 0x0ff]) ^ sbox3[(nLo >>> 8) & 0x0ff]) + sbox4[nLo & 0x0ff])
0376: ^ pbox[4];
0377: nLo ^= (((sbox1[nHi >>> 24] + sbox2[(nHi >>> 16) & 0x0ff]) ^ sbox3[(nHi >>> 8) & 0x0ff]) + sbox4[nHi & 0x0ff])
0378: ^ pbox[5];
0379: nHi ^= (((sbox1[nLo >>> 24] + sbox2[(nLo >>> 16) & 0x0ff]) ^ sbox3[(nLo >>> 8) & 0x0ff]) + sbox4[nLo & 0x0ff])
0380: ^ pbox[6];
0381: nLo ^= (((sbox1[nHi >>> 24] + sbox2[(nHi >>> 16) & 0x0ff]) ^ sbox3[(nHi >>> 8) & 0x0ff]) + sbox4[nHi & 0x0ff])
0382: ^ pbox[7];
0383: nHi ^= (((sbox1[nLo >>> 24] + sbox2[(nLo >>> 16) & 0x0ff]) ^ sbox3[(nLo >>> 8) & 0x0ff]) + sbox4[nLo & 0x0ff])
0384: ^ pbox[8];
0385: nLo ^= (((sbox1[nHi >>> 24] + sbox2[(nHi >>> 16) & 0x0ff]) ^ sbox3[(nHi >>> 8) & 0x0ff]) + sbox4[nHi & 0x0ff])
0386: ^ pbox[9];
0387: nHi ^= (((sbox1[nLo >>> 24] + sbox2[(nLo >>> 16) & 0x0ff]) ^ sbox3[(nLo >>> 8) & 0x0ff]) + sbox4[nLo & 0x0ff])
0388: ^ pbox[10];
0389: nLo ^= (((sbox1[nHi >>> 24] + sbox2[(nHi >>> 16) & 0x0ff]) ^ sbox3[(nHi >>> 8) & 0x0ff]) + sbox4[nHi & 0x0ff])
0390: ^ pbox[11];
0391: nHi ^= (((sbox1[nLo >>> 24] + sbox2[(nLo >>> 16) & 0x0ff]) ^ sbox3[(nLo >>> 8) & 0x0ff]) + sbox4[nLo & 0x0ff])
0392: ^ pbox[12];
0393: nLo ^= (((sbox1[nHi >>> 24] + sbox2[(nHi >>> 16) & 0x0ff]) ^ sbox3[(nHi >>> 8) & 0x0ff]) + sbox4[nHi & 0x0ff])
0394: ^ pbox[13];
0395: nHi ^= (((sbox1[nLo >>> 24] + sbox2[(nLo >>> 16) & 0x0ff]) ^ sbox3[(nLo >>> 8) & 0x0ff]) + sbox4[nLo & 0x0ff])
0396: ^ pbox[14];
0397: nLo ^= (((sbox1[nHi >>> 24] + sbox2[(nHi >>> 16) & 0x0ff]) ^ sbox3[(nHi >>> 8) & 0x0ff]) + sbox4[nHi & 0x0ff])
0398: ^ pbox[15];
0399: nHi ^= (((sbox1[nLo >>> 24] + sbox2[(nLo >>> 16) & 0x0ff]) ^ sbox3[(nLo >>> 8) & 0x0ff]) + sbox4[nLo & 0x0ff])
0400: ^ pbox[16];
0401:
0402: // finalize, cross and return the reassembled block
0403:
0404: return makeLong(nHi, nLo ^ pbox[17]);
0405: }
0406:
0407: // internal routine to decrypt a 64bit block
0408: protected long decryptBlock(long lCipherBlock) {
0409: // (same as above)
0410:
0411: int nHi = longHi32(lCipherBlock);
0412: int nLo = longLo32(lCipherBlock);
0413:
0414: nHi ^= m_pbox[17];
0415: nLo ^= (((m_sbox1[nHi >>> 24] + m_sbox2[(nHi >>> 16) & 0x0ff]) ^ m_sbox3[(nHi >>> 8) & 0x0ff]) + m_sbox4[nHi & 0x0ff])
0416: ^ m_pbox[16];
0417: nHi ^= (((m_sbox1[nLo >>> 24] + m_sbox2[(nLo >>> 16) & 0x0ff]) ^ m_sbox3[(nLo >>> 8) & 0x0ff]) + m_sbox4[nLo & 0x0ff])
0418: ^ m_pbox[15];
0419: nLo ^= (((m_sbox1[nHi >>> 24] + m_sbox2[(nHi >>> 16) & 0x0ff]) ^ m_sbox3[(nHi >>> 8) & 0x0ff]) + m_sbox4[nHi & 0x0ff])
0420: ^ m_pbox[14];
0421: nHi ^= (((m_sbox1[nLo >>> 24] + m_sbox2[(nLo >>> 16) & 0x0ff]) ^ m_sbox3[(nLo >>> 8) & 0x0ff]) + m_sbox4[nLo & 0x0ff])
0422: ^ m_pbox[13];
0423: nLo ^= (((m_sbox1[nHi >>> 24] + m_sbox2[(nHi >>> 16) & 0x0ff]) ^ m_sbox3[(nHi >>> 8) & 0x0ff]) + m_sbox4[nHi & 0x0ff])
0424: ^ m_pbox[12];
0425: nHi ^= (((m_sbox1[nLo >>> 24] + m_sbox2[(nLo >>> 16) & 0x0ff]) ^ m_sbox3[(nLo >>> 8) & 0x0ff]) + m_sbox4[nLo & 0x0ff])
0426: ^ m_pbox[11];
0427: nLo ^= (((m_sbox1[nHi >>> 24] + m_sbox2[(nHi >>> 16) & 0x0ff]) ^ m_sbox3[(nHi >>> 8) & 0x0ff]) + m_sbox4[nHi & 0x0ff])
0428: ^ m_pbox[10];
0429: nHi ^= (((m_sbox1[nLo >>> 24] + m_sbox2[(nLo >>> 16) & 0x0ff]) ^ m_sbox3[(nLo >>> 8) & 0x0ff]) + m_sbox4[nLo & 0x0ff])
0430: ^ m_pbox[9];
0431: nLo ^= (((m_sbox1[nHi >>> 24] + m_sbox2[(nHi >>> 16) & 0x0ff]) ^ m_sbox3[(nHi >>> 8) & 0x0ff]) + m_sbox4[nHi & 0x0ff])
0432: ^ m_pbox[8];
0433: nHi ^= (((m_sbox1[nLo >>> 24] + m_sbox2[(nLo >>> 16) & 0x0ff]) ^ m_sbox3[(nLo >>> 8) & 0x0ff]) + m_sbox4[nLo & 0x0ff])
0434: ^ m_pbox[7];
0435: nLo ^= (((m_sbox1[nHi >>> 24] + m_sbox2[(nHi >>> 16) & 0x0ff]) ^ m_sbox3[(nHi >>> 8) & 0x0ff]) + m_sbox4[nHi & 0x0ff])
0436: ^ m_pbox[6];
0437: nHi ^= (((m_sbox1[nLo >>> 24] + m_sbox2[(nLo >>> 16) & 0x0ff]) ^ m_sbox3[(nLo >>> 8) & 0x0ff]) + m_sbox4[nLo & 0x0ff])
0438: ^ m_pbox[5];
0439: nLo ^= (((m_sbox1[nHi >>> 24] + m_sbox2[(nHi >>> 16) & 0x0ff]) ^ m_sbox3[(nHi >>> 8) & 0x0ff]) + m_sbox4[nHi & 0x0ff])
0440: ^ m_pbox[4];
0441: nHi ^= (((m_sbox1[nLo >>> 24] + m_sbox2[(nLo >>> 16) & 0x0ff]) ^ m_sbox3[(nLo >>> 8) & 0x0ff]) + m_sbox4[nLo & 0x0ff])
0442: ^ m_pbox[3];
0443: nLo ^= (((m_sbox1[nHi >>> 24] + m_sbox2[(nHi >>> 16) & 0x0ff]) ^ m_sbox3[(nHi >>> 8) & 0x0ff]) + m_sbox4[nHi & 0x0ff])
0444: ^ m_pbox[2];
0445: nHi ^= (((m_sbox1[nLo >>> 24] + m_sbox2[(nLo >>> 16) & 0x0ff]) ^ m_sbox3[(nLo >>> 8) & 0x0ff]) + m_sbox4[nLo & 0x0ff])
0446: ^ m_pbox[1];
0447:
0448: return makeLong(nHi, nLo ^ m_pbox[0]);
0449: }
0450:
0451: /**
0452: * Encrypts a byte buffer (should be aligned to an 8 byte border) to another
0453: * buffer (of the same size or bigger)
0454: *
0455: * @param inbuffer buffer with plaintext data
0456: * @param outbuffer buffer to get the ciphertext data
0457: */
0458: public void encrypt(byte[] inbuffer, byte[] outbuffer) {
0459: int nLen = inbuffer.length;
0460: long lTemp;
0461: for (int nI = 0; nI < nLen; nI += 8) {
0462: // encrypt a temporary 64bit block
0463: lTemp = byteArrayToLong(inbuffer, nI);
0464: lTemp = encryptBlock(lTemp);
0465: longToByteArray(lTemp, outbuffer, nI);
0466: }
0467: }
0468:
0469: /**
0470: * encrypts a byte buffer (should be aligned to an 8 byte border) to itself
0471: * @param buffer buffer to encrypt
0472: */
0473: public void encrypt(byte[] buffer) {
0474: int nLen = buffer.length;
0475: long lTemp;
0476: for (int nI = 0; nI < nLen; nI += 8) {
0477: // encrypt a temporary 64bit block
0478: lTemp = byteArrayToLong(buffer, nI);
0479: lTemp = encryptBlock(lTemp);
0480: longToByteArray(lTemp, buffer, nI);
0481: }
0482: }
0483:
0484: /**
0485: * encrypts an integer buffer (should be aligned to an
0486: * two integer border) to another int buffer (of the
0487: * same size or bigger)
0488: * @param inbuffer buffer with plaintext data
0489: * @param outbuffer buffer to get the ciphertext data
0490: */
0491: public void encrypt(int[] inbuffer, int[] outbuffer) {
0492: int nLen = inbuffer.length;
0493: long lTemp;
0494: for (int nI = 0; nI < nLen; nI += 2) {
0495: // encrypt a temporary 64bit block
0496: lTemp = intArrayToLong(inbuffer, nI);
0497: lTemp = encryptBlock(lTemp);
0498: longToIntArray(lTemp, outbuffer, nI);
0499: }
0500: }
0501:
0502: /**
0503: * encrypts an int buffer (should be aligned to a
0504: * two integer border)
0505: * @param buffer buffer to encrypt
0506: */
0507: public void encrypt(int[] buffer) {
0508: int nLen = buffer.length;
0509: long lTemp;
0510: for (int nI = 0; nI < nLen; nI += 2) {
0511: // encrypt a temporary 64bit block
0512: lTemp = intArrayToLong(buffer, nI);
0513: lTemp = encryptBlock(lTemp);
0514: longToIntArray(lTemp, buffer, nI);
0515: }
0516: }
0517:
0518: /**
0519: * encrypts a long buffer to another long buffer (of the same size or bigger)
0520: * @param inbuffer buffer with plaintext data
0521: * @param outbuffer buffer to get the ciphertext data
0522: */
0523: public void encrypt(long[] inbuffer, long[] outbuffer) {
0524: int nLen = inbuffer.length;
0525: for (int nI = 0; nI < nLen; nI++) {
0526: outbuffer[nI] = encryptBlock(inbuffer[nI]);
0527: }
0528: }
0529:
0530: /**
0531: * encrypts a long buffer to itself
0532: * @param buffer buffer to encrypt
0533: */
0534: public void encrypt(long[] buffer) {
0535: int nLen = buffer.length;
0536: for (int nI = 0; nI < nLen; nI++) {
0537: buffer[nI] = encryptBlock(buffer[nI]);
0538: }
0539: }
0540:
0541: /**
0542: * decrypts a byte buffer (should be aligned to an 8 byte border)
0543: * to another byte buffer (of the same size or bigger)
0544: * @param inbuffer buffer with ciphertext data
0545: * @param outbuffer buffer to get the plaintext data
0546: */
0547: public void decrypt(byte[] inbuffer, byte[] outbuffer) {
0548: int nLen = inbuffer.length;
0549: long lTemp;
0550: for (int nI = 0; nI < nLen; nI += 8) {
0551: // decrypt a temporary 64bit block
0552: lTemp = byteArrayToLong(inbuffer, nI);
0553: lTemp = decryptBlock(lTemp);
0554: longToByteArray(lTemp, outbuffer, nI);
0555: }
0556: }
0557:
0558: /**
0559: * decrypts a byte buffer (should be aligned to an 8 byte border) to itself
0560: * @param buffer buffer to decrypt
0561: */
0562: public void decrypt(byte[] buffer) {
0563: int nLen = buffer.length;
0564: long lTemp;
0565: for (int nI = 0; nI < nLen; nI += 8) {
0566: // decrypt over a temporary 64bit block
0567: lTemp = byteArrayToLong(buffer, nI);
0568: lTemp = decryptBlock(lTemp);
0569: longToByteArray(lTemp, buffer, nI);
0570: }
0571: }
0572:
0573: /**
0574: * decrypts an integer buffer (should be aligned to an
0575: * two integer border) to another int buffer (of the same size or bigger)
0576: * @param inbuffer buffer with ciphertext data
0577: * @param outbuffer buffer to get the plaintext data
0578: */
0579: public void decrypt(int[] inbuffer, int[] outbuffer) {
0580: int nLen = inbuffer.length;
0581: long lTemp;
0582: for (int nI = 0; nI < nLen; nI += 2) {
0583: // decrypt a temporary 64bit block
0584: lTemp = intArrayToLong(inbuffer, nI);
0585: lTemp = decryptBlock(lTemp);
0586: longToIntArray(lTemp, outbuffer, nI);
0587: }
0588: }
0589:
0590: /**
0591: * decrypts an int buffer (should be aligned to an
0592: * two integer border)
0593: * @param buffer buffer to decrypt
0594: */
0595: public void decrypt(int[] buffer) {
0596: int nLen = buffer.length;
0597: long lTemp;
0598: for (int nI = 0; nI < nLen; nI += 2) {
0599: // decrypt a temporary 64bit block
0600: lTemp = intArrayToLong(buffer, nI);
0601: lTemp = decryptBlock(lTemp);
0602: longToIntArray(lTemp, buffer, nI);
0603: }
0604: }
0605:
0606: /**
0607: * decrypts a long buffer to another long buffer (of the same size or bigger)
0608: * @param inbuffer buffer with ciphertext data
0609: * @param outbuffer buffer to get the plaintext data
0610: */
0611: public void decrypt(long[] inbuffer, long[] outbuffer) {
0612: int nLen = inbuffer.length;
0613: for (int nI = 0; nI < nLen; nI++) {
0614: outbuffer[nI] = decryptBlock(inbuffer[nI]);
0615: }
0616: }
0617:
0618: /**
0619: * decrypts a long buffer to itself
0620: * @param buffer buffer to decrypt
0621: */
0622: public void decrypt(long[] buffer) {
0623:
0624: int nLen = buffer.length;
0625: for (int nI = 0; nI < nLen; nI++) {
0626: buffer[nI] = decryptBlock(buffer[nI]);
0627: }
0628: }
0629:
0630: // the boxes init. data,
0631: // FIXME: it might be better to create them at runtime to make the class
0632: // file smaller, e.g. by calculating the hexdigits of pi (default)
0633: // or just a fixed random sequence (out of the standard)
0634:
0635: final static int pbox_init[] = {
0636:
0637: 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822,
0638: 0x299f31d0, 0x082efa98, 0xec4e6c89, 0x452821e6,
0639: 0x38d01377, 0xbe5466cf, 0x34e90c6c, 0xc0ac29b7,
0640: 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9,
0641: 0x8979fb1b };
0642:
0643: final static int sbox_init_1[] = {
0644:
0645: 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed,
0646: 0x6a267e96, 0xba7c9045, 0xf12c7f99, 0x24a19947,
0647: 0xb3916cf7, 0x0801f2e2, 0x858efc16, 0x636920d8,
0648: 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f,
0649: 0x728eb658, 0x718bcd58, 0x82154aee, 0x7b54a41d,
0650: 0xc25a59b5, 0x9c30d539, 0x2af26013, 0xc5d1b023,
0651: 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0,
0652: 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1,
0653: 0xbd314b27, 0x78af2fda, 0x55605c60, 0xe65525f3,
0654: 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a,
0655: 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, 0xa15486af,
0656: 0x7c72e993, 0xb3ee1411, 0x636fbc2a, 0x2ba9c55d,
0657: 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33,
0658: 0x6c24cf5c, 0x7a325381, 0x28958677, 0x3b8f4898,
0659: 0x6b4bb9af, 0xc4bfe81b, 0x66282193, 0x61d809cc,
0660: 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d,
0661: 0xe98575b1, 0xdc262302, 0xeb651b88, 0x23893e81,
0662: 0xd396acc5, 0x0f6d6ff3, 0x83f44239, 0x2e0b4482,
0663: 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842,
0664: 0xf6e96c9a, 0x670c9c61, 0xabd388f0, 0x6a51a0d2,
0665: 0xd8542f68, 0x960fa728, 0xab5133a3, 0x6eef0b6c,
0666: 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d,
0667: 0x39af0176, 0x66ca593e, 0x82430e88, 0x8cee8619,
0668: 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, 0xe06f75d8,
0669: 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62,
0670: 0x363f7706, 0x1bfedf72, 0x429b023d, 0x37d0d724,
0671: 0xd00a1248, 0xdb0fead3, 0x49f1c09b, 0x075372c9,
0672: 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a,
0673: 0xb6794c3b, 0x976ce0bd, 0x04c006ba, 0xc1a94fb6,
0674: 0x409f60c4, 0x5e5c9ec2, 0x196a2463, 0x68fb6faf,
0675: 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f,
0676: 0x9b30952c, 0xcc814544, 0xaf5ebd09, 0xbee3d004,
0677: 0xde334afd, 0x660f2807, 0x192e4bb3, 0xc0cba857,
0678: 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd,
0679: 0x1a60320a, 0xd6a100c6, 0x402c7279, 0x679f25fe,
0680: 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, 0x3c7516df,
0681: 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa,
0682: 0xfd238760, 0x53317b48, 0x3e00df82, 0x9e5c57bb,
0683: 0xca6f8ca0, 0x1a87562e, 0xdf1769db, 0xd542a8f6,
0684: 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0,
0685: 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98,
0686: 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, 0x9a53e479,
0687: 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da,
0688: 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, 0xef20cada,
0689: 0x36774c01, 0xd07e9efe, 0x2bf11fb4, 0x95dbda4d,
0690: 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0,
0691: 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb,
0692: 0xf2122b64, 0x8888b812, 0x900df01c, 0x4fad5ea0,
0693: 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218,
0694: 0xbe0e1777, 0xea752dfe, 0x8b021fa1, 0xe5a0cc0f,
0695: 0xb56f74e8, 0x18acf3d6, 0xce89e299, 0xb4a84fe0,
0696: 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266,
0697: 0x80957705, 0x93cc7314, 0x211a1477, 0xe6ad2065,
0698: 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, 0xebcdaf0c,
0699: 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d,
0700: 0x2071b35e, 0x226800bb, 0x57b8e0af, 0x2464369b,
0701: 0xf009b91e, 0x5563911d, 0x59dfa6aa, 0x78c14389,
0702: 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376,
0703: 0x6295cfa9, 0x11c81968, 0x4e734a41, 0xb3472dca,
0704: 0x7b14a94a, 0x1b510052, 0x9a532915, 0xd60f573f,
0705: 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5,
0706: 0x571be91f, 0xf296ec6b, 0x2a0dd915, 0xb6636521,
0707: 0xe7b9f9b6, 0xff34052e, 0xc5855664, 0x53b02d5d,
0708: 0xa99f8fa1, 0x08ba4799, 0x6e85076a };
0709:
0710: final static int sbox_init_2[] = {
0711:
0712: 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0,
0713: 0x49a7df7d, 0x9cee60b8, 0x8fedb266, 0xecaa8c71,
0714: 0x699a17ff, 0x5664526c, 0xc2b19ee1, 0x193602a5,
0715: 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a,
0716: 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07,
0717: 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, 0x4cdd2086,
0718: 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f,
0719: 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, 0x687f3584,
0720: 0x52a0e286, 0xb79c5305, 0xaa500737, 0x3e07841c,
0721: 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37,
0722: 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, 0xae0cf51a,
0723: 0x3cb574b2, 0x25837a58, 0xdc0921bd, 0xd19113f9,
0724: 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581,
0725: 0x37c2dadc, 0xc8b57634, 0x9af3dda7, 0xa9446146,
0726: 0x0fd0030e, 0xecc8c73e, 0xa4751e41, 0xe238cd99,
0727: 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38,
0728: 0x4f6db908, 0x6f420d03, 0xf60a04bf, 0x2cb81290,
0729: 0x24977c79, 0x5679b072, 0xbcaf89af, 0xde9a771f,
0730: 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f,
0731: 0x2e6b7124, 0x501adde6, 0x9f84cd87, 0x7a584718,
0732: 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, 0xec7aec3a,
0733: 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847,
0734: 0x3215d908, 0xdd433b37, 0x24c2ba16, 0x12a14d43,
0735: 0x2a65c451, 0x50940002, 0x133ae4dd, 0x71dff89e,
0736: 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1,
0737: 0xd7a3c76b, 0x3c11183b, 0x5924a509, 0xf28fe6ed,
0738: 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, 0x86e34570,
0739: 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c,
0740: 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, 0x803e89d6,
0741: 0x5266c825, 0x2e4cc978, 0x9c10b36a, 0xc6150eba,
0742: 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7,
0743: 0x361d2b3d, 0x1939260f, 0x19c27960, 0x5223a708,
0744: 0xf71312b6, 0xebadfe6e, 0xeac31f66, 0xe3bc4595,
0745: 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef,
0746: 0xbe6c5aa5, 0x65582185, 0x68ab9802, 0xeecea50f,
0747: 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, 0x1521b628,
0748: 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830,
0749: 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, 0xb5735c90,
0750: 0x4c70a239, 0xd59e9e0b, 0xcbaade14, 0xeecc86bc,
0751: 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf,
0752: 0x19bdf0ca, 0xa02369b9, 0x655abb50, 0x40685a32,
0753: 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, 0x9b540b19,
0754: 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a,
0755: 0x97e32d77, 0x11ed935f, 0x16681281, 0x0e358829,
0756: 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, 0x57f584a5,
0757: 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb,
0758: 0x532e3054, 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef,
0759: 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, 0x5d4a14d9,
0760: 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6,
0761: 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, 0xc742f442,
0762: 0xef6abbb5, 0x654f3b1d, 0x41cd2105, 0xd81e799e,
0763: 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2,
0764: 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3,
0765: 0x69cb7492, 0x47848a0b, 0x5692b285, 0x095bbf00,
0766: 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a,
0767: 0x0c55f5ea, 0x1dadf43e, 0x233f7061, 0x3372f092,
0768: 0x8d937e41, 0xd65fecf1, 0x6c223bdb, 0x7cde3759,
0769: 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084,
0770: 0x19f8509e, 0xe8efd855, 0x61d99735, 0xa969a7aa,
0771: 0xc50c06c2, 0x5a04abfc, 0x800bcadc, 0x9e447a2e,
0772: 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3,
0773: 0x105588cd, 0x675fda79, 0xe3674340, 0xc5c43465,
0774: 0x713e38d8, 0x3d28f89e, 0xf16dff20, 0x153e21e7,
0775: 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7 };
0776:
0777: final static int sbox_init_3[] = {
0778:
0779: 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7,
0780: 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, 0xd4082471,
0781: 0x3320f46a, 0x43b7d4b7, 0x500061af, 0x1e39f62e,
0782: 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d,
0783: 0x96b591af, 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec,
0784: 0x03bd9785, 0x7fac6dd0, 0x31cb8504, 0x96eb27b3,
0785: 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825,
0786: 0x530429f4, 0x0a2c86da, 0xe9b66dfb, 0x68dc1462,
0787: 0xd7486900, 0x680ec0a4, 0x27a18dee, 0x4f3ffea2,
0788: 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c,
0789: 0xd3375fec, 0xce78a399, 0x406b2a42, 0x20fe9e35,
0790: 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, 0x1dc9faf7,
0791: 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74,
0792: 0xdd5b4332, 0x6841e7f7, 0xca7820fb, 0xfb0af54e,
0793: 0xd8feb397, 0x454056ac, 0xba489527, 0x55533a3a,
0794: 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc,
0795: 0xa1159a58, 0xcca92963, 0x99e1db33, 0xa62a4a56,
0796: 0x3f3125f9, 0x5ef47e1c, 0x9029317c, 0xfdf8e802,
0797: 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548,
0798: 0xe4c66d22, 0x48c1133f, 0xc70f86dc, 0x07f9c9ee,
0799: 0x41041f0f, 0x404779a4, 0x5d886e17, 0x325f51eb,
0800: 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834,
0801: 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2,
0802: 0x02e1329e, 0xaf664fd1, 0xcad18115, 0x6b2395e0,
0803: 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e,
0804: 0xe6ba0d99, 0xde720c8c, 0x2da2f728, 0xd0127845,
0805: 0x95b794fd, 0x647d0862, 0xe7ccf5f0, 0x5449a36f,
0806: 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341,
0807: 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60,
0808: 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, 0xc67b5510,
0809: 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7,
0810: 0xcc00ffa3, 0xb5390f92, 0x690fed0b, 0x667b9ffb,
0811: 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, 0xbb132f88,
0812: 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3,
0813: 0xcc115979, 0x8026e297, 0xf42e312d, 0x6842ada7,
0814: 0xc66a2b3b, 0x12754ccc, 0x782ef11c, 0x6a124237,
0815: 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018,
0816: 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, 0x44421659,
0817: 0x0a121386, 0xd90cec6e, 0xd5abea2a, 0x64af674e,
0818: 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057,
0819: 0xf0f7c086, 0x60787bf8, 0x6003604d, 0xd1fd8346,
0820: 0xf6381fb0, 0x7745ae04, 0xd736fccc, 0x83426b33,
0821: 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be,
0822: 0xbde8ae24, 0x55464299, 0xbf582e61, 0x4e58f48f,
0823: 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, 0x5366f9c3,
0824: 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661,
0825: 0x8b1ddf84, 0x846a0e79, 0x915f95e2, 0x466e598e,
0826: 0x20b45770, 0x8cd55591, 0xc902de4c, 0xb90bace1,
0827: 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6,
0828: 0xe0a9dc09, 0x662d09a1, 0xc4324633, 0xe85a1f02,
0829: 0x09f0be8c, 0x4a99a025, 0x1d6efe10, 0x1ab93d1d,
0830: 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83,
0831: 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01,
0832: 0xa70683fa, 0xa002b5c4, 0x0de6d027, 0x9af88c27,
0833: 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28,
0834: 0xc0f586e0, 0x006058aa, 0x30dc7d62, 0x11e69ed7,
0835: 0x2338ea63, 0x53c2dd94, 0xc2c21634, 0xbbcbee56,
0836: 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409,
0837: 0x4b7c0188, 0x39720a3d, 0x7c927c24, 0x86e3725f,
0838: 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, 0xed545578,
0839: 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e,
0840: 0xb161e6f8, 0xa28514d9, 0x6c51133c, 0x6fd5c7e7,
0841: 0x56e14ec4, 0x362abfce, 0xddc6c837, 0xd79a3234,
0842: 0x92638212, 0x670efa8e, 0x406000e0 };
0843:
0844: final static int sbox_init_4[] = {
0845:
0846: 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e,
0847: 0x4fa33742, 0xd3822740, 0x99bc9bbe, 0xd5118e9d,
0848: 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, 0xb78c1b6b,
0849: 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f,
0850: 0xbc946e79, 0xc6a376d2, 0x6549c2c8, 0x530ff8ee,
0851: 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, 0x2939bbdb,
0852: 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0,
0853: 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, 0xc089c2b8,
0854: 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, 0x83c061ba,
0855: 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9,
0856: 0xa73a3ae1, 0x4ba99586, 0xef5562e9, 0xc72fefd3,
0857: 0xf752f7da, 0x3f046f69, 0x77fa0a59, 0x80e4a915,
0858: 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a,
0859: 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a,
0860: 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, 0x1f9f25cf,
0861: 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71,
0862: 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d,
0863: 0x283b57cc, 0xf8d56629, 0x79132e28, 0x785f0191,
0864: 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4,
0865: 0x88f46dba, 0x03a16125, 0x0564f0bd, 0xc3eb9e15,
0866: 0x3c9057a2, 0x97271aec, 0xa93a072a, 0x1b3f6d9b,
0867: 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928,
0868: 0xb155fdf5, 0x03563482, 0x8aba3cbb, 0x28517711,
0869: 0xc20ad9f8, 0xabcc5167, 0xccad925f, 0x4de81751,
0870: 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2,
0871: 0xfb3e7bce, 0x5121ce64, 0x774fbe32, 0xa8b6e37e,
0872: 0xc3293d46, 0x48de5369, 0x6413e680, 0xa2ae0810,
0873: 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a,
0874: 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd,
0875: 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, 0xdda26a7e,
0876: 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8,
0877: 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, 0xd29be463,
0878: 0x542f5d9e, 0xaec2771b, 0xf64e6370, 0x740e0d8d,
0879: 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08,
0880: 0x4eb4e2cc, 0x34d2466a, 0x0115af84, 0xe1b00428,
0881: 0x95983a1d, 0x06b89fb4, 0xce6ea048, 0x6f3f3b82,
0882: 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1,
0883: 0xe7933fdc, 0xbb3a792b, 0x344525bd, 0xa08839e1,
0884: 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, 0xe01cc87e,
0885: 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749,
0886: 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, 0x0339c32a,
0887: 0xc6913667, 0x8df9317c, 0xe0b12b4f, 0xf79e59b7,
0888: 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c,
0889: 0x15e6fc2a, 0x0f91fc71, 0x9b941525, 0xfae59361,
0890: 0xceb69ceb, 0xc2a86459, 0x12baa8d1, 0xb6c1075e,
0891: 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e,
0892: 0x1698db3b, 0x4c98a0be, 0x3278e964, 0x9f1f9532,
0893: 0xe0d392df, 0xd3a0342b, 0x8971f21e, 0x1b0a7441,
0894: 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d,
0895: 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, 0xe54cda54,
0896: 0x1edad891, 0xce6279cf, 0xcd3e7e6f, 0x1618b166,
0897: 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357,
0898: 0xa6327623, 0x93a83531, 0x56cccd02, 0xacf08162,
0899: 0x5a75ebb5, 0x6e163697, 0x88d273cc, 0xde966292,
0900: 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd,
0901: 0x327a140a, 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd,
0902: 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, 0x71126905,
0903: 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0,
0904: 0x1640e3d3, 0x38abbd60, 0x2547adf0, 0xba38209c,
0905: 0xf746ce76, 0x77afa1c5, 0x20756060, 0x85cbfe4e,
0906: 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c,
0907: 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, 0x90d4f869,
0908: 0xa65cdea0, 0x3f09252d, 0xc208e69f, 0xb74e6132,
0909: 0xce77e25b, 0x578fdfe3, 0x3ac372e6 };
0910: }
0911:
0912: private static class BlowfishCBC extends BlowfishECB {
0913:
0914: // here we hold the CBC IV
0915: long m_lCBCIV;
0916:
0917: /**
0918: * get the current CBC IV (for cipher resets)
0919: * @return current CBC IV
0920: */
0921: public long getCBCIV() {
0922: return m_lCBCIV;
0923: }
0924:
0925: /**
0926: * get the current CBC IV (for cipher resets)
0927: * @param dest wher eto put current CBC IV in network byte ordered array
0928: */
0929: public void getCBCIV(byte[] dest) {
0930: longToByteArray(m_lCBCIV, dest, 0);
0931: }
0932:
0933: /**
0934: * set the current CBC IV (for cipher resets)
0935: * @param lNewCBCIV the new CBC IV
0936: */
0937: public void setCBCIV(long lNewCBCIV) {
0938: m_lCBCIV = lNewCBCIV;
0939: }
0940:
0941: /**
0942: * set the current CBC IV (for cipher resets)
0943: * @param newCBCIV the new CBC IV in network byte ordered array
0944: */
0945: public void setCBCIV(byte[] newCBCIV) {
0946: m_lCBCIV = byteArrayToLong(newCBCIV, 0);
0947: }
0948:
0949: /**
0950: * constructor, stores a zero CBC IV
0951: * @param bfkey key material, up to MAXKEYLENGTH bytes
0952: */
0953: public BlowfishCBC(byte[] bfkey) {
0954: super (bfkey);
0955:
0956: // store zero CBCB IV
0957: setCBCIV(0);
0958: }
0959:
0960: /**
0961: * constructor
0962: * @param bfkey key material, up to MAXKEYLENGTH bytes
0963: * @param lInitCBCIV the CBC IV
0964: */
0965: public BlowfishCBC(byte[] bfkey, long lInitCBCIV) {
0966: super (bfkey);
0967:
0968: // store the CBCB IV
0969: setCBCIV(lInitCBCIV);
0970: }
0971:
0972: /**
0973: * constructor
0974: * @param bfkey key material, up to MAXKEYLENGTH bytes
0975: * @param initCBCIV the CBC IV (array with min. BLOCKSIZE bytes)
0976: */
0977: public BlowfishCBC(byte[] bfkey, byte[] initCBCIV) {
0978: super (bfkey);
0979:
0980: // store the CBCB IV
0981: setCBCIV(initCBCIV);
0982: }
0983:
0984: /**
0985: * cleans up all critical internals,
0986: * call this if you don't need an instance anymore
0987: */
0988: public void cleanUp() {
0989: m_lCBCIV = 0;
0990: super .cleanUp();
0991: }
0992:
0993: // internal routine to encrypt a block in CBC mode
0994: private long encryptBlockCBC(long lPlainblock) {
0995: // chain with the CBC IV
0996: lPlainblock ^= m_lCBCIV;
0997:
0998: // encrypt the block
0999: lPlainblock = super .encryptBlock(lPlainblock);
1000:
1001: // the encrypted block is the new CBC IV
1002: return (m_lCBCIV = lPlainblock);
1003: }
1004:
1005: // internal routine to decrypt a block in CBC mode
1006: private long decryptBlockCBC(long lCipherblock) {
1007: // save the current block
1008: long lTemp = lCipherblock;
1009:
1010: // decrypt the block
1011: lCipherblock = super .decryptBlock(lCipherblock);
1012:
1013: // dechain the block
1014: lCipherblock ^= m_lCBCIV;
1015:
1016: // set the new CBC IV
1017: m_lCBCIV = lTemp;
1018:
1019: // return the decrypted block
1020: return lCipherblock;
1021: }
1022:
1023: /**
1024: * encrypts a byte buffer (should be aligned to an 8 byte border)
1025: * to another buffer (of the same size or bigger)
1026: * @param inbuffer buffer with plaintext data
1027: * @param outbuffer buffer to get the ciphertext data
1028: */
1029: public void encrypt(byte[] inbuffer, byte[] outbuffer) {
1030: int nLen = inbuffer.length;
1031: long lTemp;
1032: for (int nI = 0; nI < nLen; nI += 8) {
1033: // encrypt a temporary 64bit block
1034: lTemp = byteArrayToLong(inbuffer, nI);
1035: lTemp = encryptBlockCBC(lTemp);
1036: longToByteArray(lTemp, outbuffer, nI);
1037: }
1038: }
1039:
1040: /**
1041: * encrypts a byte buffer (should be aligned to an 8 byte border) to itself
1042: * @param buffer buffer to encrypt
1043: */
1044: public void encrypt(byte[] buffer) {
1045:
1046: int nLen = buffer.length;
1047: long lTemp;
1048: for (int nI = 0; nI < nLen; nI += 8) {
1049: // encrypt a temporary 64bit block
1050: lTemp = byteArrayToLong(buffer, nI);
1051: lTemp = encryptBlockCBC(lTemp);
1052: longToByteArray(lTemp, buffer, nI);
1053: }
1054: }
1055:
1056: /**
1057: * encrypts an int buffer (should be aligned to an
1058: * two integer border) to another int buffer (of the same
1059: * size or bigger)
1060: * @param inbuffer buffer with plaintext data
1061: * @param outbuffer buffer to get the ciphertext data
1062: */
1063: public void encrypt(int[] inbuffer, int[] outbuffer) {
1064: int nLen = inbuffer.length;
1065: long lTemp;
1066: for (int nI = 0; nI < nLen; nI += 2) {
1067: // encrypt a temporary 64bit block
1068: lTemp = intArrayToLong(inbuffer, nI);
1069: lTemp = encryptBlockCBC(lTemp);
1070: longToIntArray(lTemp, outbuffer, nI);
1071: }
1072: }
1073:
1074: /**
1075: * encrypts an integer buffer (should be aligned to an
1076: * @param buffer buffer to encrypt
1077: */
1078: public void encrypt(int[] buffer) {
1079: int nLen = buffer.length;
1080: long lTemp;
1081: for (int nI = 0; nI < nLen; nI += 2) {
1082: // encrypt a temporary 64bit block
1083: lTemp = intArrayToLong(buffer, nI);
1084: lTemp = encryptBlockCBC(lTemp);
1085: longToIntArray(lTemp, buffer, nI);
1086: }
1087: }
1088:
1089: /**
1090: * encrypts a long buffer to another long buffer (of the same size or bigger)
1091: * @param inbuffer buffer with plaintext data
1092: * @param outbuffer buffer to get the ciphertext data
1093: */
1094: public void encrypt(long[] inbuffer, long[] outbuffer) {
1095: int nLen = inbuffer.length;
1096: for (int nI = 0; nI < nLen; nI++) {
1097: outbuffer[nI] = encryptBlockCBC(inbuffer[nI]);
1098: }
1099: }
1100:
1101: /**
1102: * encrypts a long buffer to itself
1103: * @param buffer buffer to encrypt
1104: */
1105: public void encrypt(long[] buffer) {
1106: int nLen = buffer.length;
1107: for (int nI = 0; nI < nLen; nI++) {
1108: buffer[nI] = encryptBlockCBC(buffer[nI]);
1109: }
1110: }
1111:
1112: /**
1113: * decrypts a byte buffer (should be aligned to an 8 byte border)
1114: * to another buffer (of the same size or bigger)
1115: * @param inbuffer buffer with ciphertext data
1116: * @param outbuffer buffer to get the plaintext data
1117: */
1118: public void decrypt(byte[] inbuffer, byte[] outbuffer) {
1119: int nLen = inbuffer.length;
1120: long lTemp;
1121: for (int nI = 0; nI < nLen; nI += 8) {
1122: // decrypt a temporary 64bit block
1123: lTemp = byteArrayToLong(inbuffer, nI);
1124: lTemp = decryptBlockCBC(lTemp);
1125: longToByteArray(lTemp, outbuffer, nI);
1126: }
1127: }
1128:
1129: /**
1130: * decrypts a byte buffer (should be aligned to an 8 byte border) to itself
1131: * @param buffer buffer to decrypt
1132: */
1133: public void decrypt(byte[] buffer) {
1134: int nLen = buffer.length;
1135: long lTemp;
1136: for (int nI = 0; nI < nLen; nI += 8) {
1137: // decrypt over a temporary 64bit block
1138: lTemp = byteArrayToLong(buffer, nI);
1139: lTemp = decryptBlockCBC(lTemp);
1140: longToByteArray(lTemp, buffer, nI);
1141: }
1142: }
1143:
1144: /**
1145: * decrypts an integer buffer (should be aligned to an
1146: * two integer border) to another int buffer (of the same size or bigger)
1147: * @param inbuffer buffer with ciphertext data
1148: * @param outbuffer buffer to get the plaintext data
1149: */
1150: public void decrypt(int[] inbuffer, int[] outbuffer) {
1151:
1152: int nLen = inbuffer.length;
1153: long lTemp;
1154: for (int nI = 0; nI < nLen; nI += 2) {
1155: // decrypt a temporary 64bit block
1156: lTemp = intArrayToLong(inbuffer, nI);
1157: lTemp = decryptBlockCBC(lTemp);
1158: longToIntArray(lTemp, outbuffer, nI);
1159: }
1160: }
1161:
1162: /**
1163: * decrypts an int buffer (should be aligned to a
1164: * two integer border)
1165: * @param buffer buffer to decrypt
1166: */
1167: public void decrypt(int[] buffer) {
1168: int nLen = buffer.length;
1169: long lTemp;
1170: for (int nI = 0; nI < nLen; nI += 2) {
1171: // decrypt a temporary 64bit block
1172: lTemp = intArrayToLong(buffer, nI);
1173: lTemp = decryptBlockCBC(lTemp);
1174: longToIntArray(lTemp, buffer, nI);
1175: }
1176: }
1177:
1178: /**
1179: * decrypts a long buffer to another long buffer (of the same size or bigger)
1180: * @param inbuffer buffer with ciphertext data
1181: * @param outbuffer buffer to get the plaintext data
1182: */
1183: public void decrypt(long[] inbuffer, long[] outbuffer) {
1184: int nLen = inbuffer.length;
1185: for (int nI = 0; nI < nLen; nI++) {
1186: outbuffer[nI] = decryptBlockCBC(inbuffer[nI]);
1187: }
1188: }
1189:
1190: /**
1191: * decrypts a long buffer to itself
1192: * @param buffer buffer to decrypt
1193: */
1194: public void decrypt(long[] buffer) {
1195: int nLen = buffer.length;
1196: for (int nI = 0; nI < nLen; nI++) {
1197: buffer[nI] = decryptBlockCBC(buffer[nI]);
1198: }
1199: }
1200:
1201: }
1202:
1203: /**
1204: * gets bytes from an array into a long
1205: * @param buffer where to get the bytes
1206: * @param nStartIndex index from where to read the data
1207: * @return the 64bit integer
1208: */
1209: private static long byteArrayToLong(byte[] buffer, int nStartIndex) {
1210: return (((long) buffer[nStartIndex]) << 56)
1211: | (((long) buffer[nStartIndex + 1] & 0x0ffL) << 48)
1212: | (((long) buffer[nStartIndex + 2] & 0x0ffL) << 40)
1213: | (((long) buffer[nStartIndex + 3] & 0x0ffL) << 32)
1214: | (((long) buffer[nStartIndex + 4] & 0x0ffL) << 24)
1215: | (((long) buffer[nStartIndex + 5] & 0x0ffL) << 16)
1216: | (((long) buffer[nStartIndex + 6] & 0x0ffL) << 8)
1217: | ((long) buffer[nStartIndex + 7] & 0x0ff);
1218: }
1219:
1220: /**
1221: * converts a long o bytes which are put into a given array
1222: * @param lValue the 64bit integer to convert
1223: * @param buffer the target buffer
1224: * @param nStartIndex where to place the bytes in the buffer
1225: */
1226: private static void longToByteArray(long lValue, byte[] buffer,
1227: int nStartIndex) {
1228: buffer[nStartIndex] = (byte) (lValue >>> 56);
1229: buffer[nStartIndex + 1] = (byte) ((lValue >>> 48) & 0x0ff);
1230: buffer[nStartIndex + 2] = (byte) ((lValue >>> 40) & 0x0ff);
1231: buffer[nStartIndex + 3] = (byte) ((lValue >>> 32) & 0x0ff);
1232: buffer[nStartIndex + 4] = (byte) ((lValue >>> 24) & 0x0ff);
1233: buffer[nStartIndex + 5] = (byte) ((lValue >>> 16) & 0x0ff);
1234: buffer[nStartIndex + 6] = (byte) ((lValue >>> 8) & 0x0ff);
1235: buffer[nStartIndex + 7] = (byte) lValue;
1236: }
1237:
1238: /**
1239: * converts values from an integer array to a long
1240: * @param buffer where to get the bytes
1241: * @param nStartIndex index from where to read the data
1242: * @return the 64bit integer
1243: */
1244: private static long intArrayToLong(int[] buffer, int nStartIndex) {
1245: return (((long) buffer[nStartIndex]) << 32)
1246: | (((long) buffer[nStartIndex + 1]) & 0x0ffffffffL);
1247: }
1248:
1249: /**
1250: * converts a long to integers which are put into a given array
1251: * @param lValue the 64bit integer to convert
1252: * @param buffer the target buffer
1253: * @param nStartIndex where to place the bytes in the buffer
1254: */
1255: private static void longToIntArray(long lValue, int[] buffer,
1256: int nStartIndex) {
1257: buffer[nStartIndex] = (int) (lValue >>> 32);
1258: buffer[nStartIndex + 1] = (int) lValue;
1259: }
1260:
1261: /**
1262: * makes a long from two integers (treated unsigned)
1263: * @param nLo lower 32bits
1264: * @param nHi higher 32bits
1265: * @return the built long
1266: */
1267: private static long makeLong(int nLo, int nHi) {
1268: return (((long) nHi << 32) | ((long) nLo & 0x00000000ffffffffL));
1269: }
1270:
1271: /**
1272: * gets the lower 32 bits of a long
1273: * @param lVal the long integer
1274: * @return lower 32 bits
1275: */
1276: private static int longLo32(long lVal) {
1277: return (int) lVal;
1278: }
1279:
1280: /**
1281: * gets the higher 32 bits of a long
1282: * @param lVal the long integer
1283: * @return higher 32 bits
1284: */
1285: private static int longHi32(long lVal) {
1286: return (int) ((lVal >>> 32));
1287: }
1288:
1289: // our table for binhex conversion
1290: final static char[] HEXTAB = { '0', '1', '2', '3', '4', '5', '6',
1291: '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
1292:
1293: /**
1294: * converts a byte array to a binhex string
1295: * @param data the byte array
1296: * @param nStartPos start index where to get the bytes
1297: * @param nNumOfBytes number of bytes to convert
1298: * @return the binhex string
1299: */
1300: private static String bytesToBinHex(byte[] data, int nStartPos,
1301: int nNumOfBytes) {
1302: StringBuilder sbuf = new StringBuilder();
1303: sbuf.setLength(nNumOfBytes << 1);
1304:
1305: int nPos = 0;
1306: for (int nI = 0; nI < nNumOfBytes; nI++) {
1307: sbuf.setCharAt(nPos++,
1308: HEXTAB[(data[nI + nStartPos] >> 4) & 0x0f]);
1309: sbuf.setCharAt(nPos++, HEXTAB[data[nI + nStartPos] & 0x0f]);
1310: }
1311: return sbuf.toString();
1312: }
1313:
1314: /**
1315: * converts a binhex string back into a byte array (invalid codes will be skipped)
1316: * @param sBinHex binhex string
1317: * @param data the target array
1318: * @param nSrcPos from which character in the string the conversion should begin,
1319: * remember that (nSrcPos modulo 2) should equals 0 normally
1320: * @param nDstPos to store the bytes from which position in the array
1321: * @param nNumOfBytes number of bytes to extract
1322: * @return number of extracted bytes
1323: */
1324: private static int binHexToBytes(String sBinHex, byte[] data,
1325: int nSrcPos, int nDstPos, int nNumOfBytes) {
1326: // check for correct ranges
1327: int nStrLen = sBinHex.length();
1328:
1329: int nAvailBytes = (nStrLen - nSrcPos) >> 1;
1330: if (nAvailBytes < nNumOfBytes) {
1331: nNumOfBytes = nAvailBytes;
1332: }
1333:
1334: int nOutputCapacity = data.length - nDstPos;
1335: if (nNumOfBytes > nOutputCapacity) {
1336: nNumOfBytes = nOutputCapacity;
1337: }
1338:
1339: // convert now
1340: int nResult = 0;
1341: for (int nI = 0; nI < nNumOfBytes; nI++) {
1342: byte bActByte = 0;
1343: boolean blConvertOK = true;
1344: for (int nJ = 0; nJ < 2; nJ++) {
1345: bActByte <<= 4;
1346: char cActChar = sBinHex.charAt(nSrcPos++);
1347:
1348: if ((cActChar >= 'a') && (cActChar <= 'f')) {
1349: bActByte |= (byte) (cActChar - 'a') + 10;
1350: } else {
1351: if ((cActChar >= '0') && (cActChar <= '9')) {
1352: bActByte |= (byte) (cActChar - '0');
1353: } else {
1354: blConvertOK = false;
1355: }
1356: }
1357: }
1358: if (blConvertOK) {
1359: data[nDstPos++] = bActByte;
1360: nResult++;
1361: }
1362: }
1363:
1364: return nResult;
1365: }
1366:
1367: /**
1368: * converts a byte array into an UNICODE string
1369: * @param data the byte array
1370: * @param nStartPos where to begin the conversion
1371: * @param nNumOfBytes number of bytes to handle
1372: * @return the string
1373: */
1374: private static String byteArrayToUNCString(byte[] data,
1375: int nStartPos, int nNumOfBytes) {
1376: // we need two bytes for every character
1377: nNumOfBytes &= ~1;
1378:
1379: // enough bytes in the buffer?
1380: int nAvailCapacity = data.length - nStartPos;
1381:
1382: if (nAvailCapacity < nNumOfBytes) {
1383: nNumOfBytes = nAvailCapacity;
1384: }
1385:
1386: StringBuilder sbuf = new StringBuilder();
1387: sbuf.setLength(nNumOfBytes >> 1);
1388:
1389: int nSBufPos = 0;
1390:
1391: while (nNumOfBytes > 0) {
1392: sbuf
1393: .setCharAt(
1394: nSBufPos++,
1395: (char) (((int) data[nStartPos] << 8) | ((int) data[nStartPos + 1] & 0x0ff)));
1396: nStartPos += 2;
1397: nNumOfBytes -= 2;
1398: }
1399:
1400: return sbuf.toString();
1401: }
1402: }
|