⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 blowfishcipher.java

📁 java高级使用教程 全书一共分六章
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
// BlowfishCipher - the Blowfish encryption method
//
// Copyright (C) 1996 by Jef Poskanzer <jef@acme.com>.  All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 1. Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
//
// Visit the ACME Labs Java page for up-to-date versions of this and other
// fine Java utilities: http://www.acme.com/java/

package Acme.Crypto;

import java.io.*;

/// The Blowfish encryption method.
// <P>
// This is surprisingly fast, for pure Java.  On a SPARC 20, wrapped
// in Acme.Crypto.EncryptedOutputStream or Acme.Crypto.EncryptedInputStream,
// it does around 8000 bytes/second, somewhat faster than Acme.Crypto.DesCipher.
// <P>
// With help from David Brownell.
// <P>
// <A HREF="/resources/classes/Acme/Crypto/BlowfishCipher.java">Fetch the software.</A><BR>
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
// <P>
// @see EncryptedOutputStream
// @see EncryptedInputStream

public class BlowfishCipher extends BlockCipher
    {

    private static final int N = 16;	// number of rounds

    // Constructor, string key.
    public BlowfishCipher( String keyStr )
	{
	super( 0, 8 );
	setKey( keyStr );
	}

    // Constructor, byte-array key.
    public BlowfishCipher( byte[] key )
	{
	super( 0, 8 );
	setKey( key );
	}


    // Key routines.

    private int[] P = new int[N + 2];
    private int[][] S = new int[4][256];

    /// Set the key.
    public void setKey( byte[] key )
	{
	int i, j, k;
	int data, datal, datar;

	// Initialize P and S.
	for ( i = 0; i < N + 2; ++i )
	    P[i] = Pinit[i];
	for ( i = 0; i < 4; ++i )
	    for ( j = 0; j < 256; ++j )
		S[i][j] = Sinit[i][j];

	// XOR the key into P.
	j = 0;
	for ( i = 0; i < N + 2; ++i )
	    {
	    data = 0x00000000;
	    for ( k = 0; k < 4; ++k )
		{
		data = ( data << 8 ) | ( key[j % key.length] & 0xff );
		++j;
		}
	    P[i] ^= data;
	    }

	// Auto-munge P and S.
	int[] datalr = { 0x00000000, 0x00000000 };
	for ( i = 0; i < N + 2; i += 2 )
	    {
	    encrypt( datalr );
	    P[i] = datalr[0];
	    P[i + 1] = datalr[1];
	    }
	for ( i = 0; i < 4; ++i )
	    {
	    for ( j = 0; j < 256; j += 2 )
		{
		encrypt( datalr );
		S[i][j] = datalr[0];
		S[i][j + 1] = datalr[1];
		}
	    }
	}


    // Block encryption routines.

    /// Encrypt a block of eight bytes.
    public void encrypt( byte[] clearText, int clearOff, byte[] cipherText, int cipherOff )
	{
	int[] tempInts = new int[2];

	squashBytesToInts( clearText, clearOff, tempInts, 0, 2 );
	encrypt( tempInts );
	spreadIntsToBytes( tempInts, 0, cipherText, cipherOff, 2 );
	}

    /// Encrypt a block of two ints.
    private void encrypt( int[] text )
	{
	int xl, xr, temp;
	int i;

	xl = text[0];
	xr = text[1];

	xl ^= P[0];
	xr ^= F( xl ) ^ P[1];
	xl ^= F( xr ) ^ P[2];
	xr ^= F( xl ) ^ P[3];
	xl ^= F( xr ) ^ P[4];
	xr ^= F( xl ) ^ P[5];
	xl ^= F( xr ) ^ P[6];
	xr ^= F( xl ) ^ P[7];
	xl ^= F( xr ) ^ P[8];
	xr ^= F( xl ) ^ P[9];
	xl ^= F( xr ) ^ P[10];
	xr ^= F( xl ) ^ P[11];
	xl ^= F( xr ) ^ P[12];
	xr ^= F( xl ) ^ P[13];
	xl ^= F( xr ) ^ P[14];
	xr ^= F( xl ) ^ P[15];
	xl ^= F( xr ) ^ P[16];
	xr ^= P[17];

	text[0] = xr;
	text[1] = xl;
	}

    /// Decrypt a block of eight bytes.
    public void decrypt( byte[] cipherText, int cipherOff, byte[] clearText, int clearOff )
	{
	int[] tempInts = new int[2];

	squashBytesToInts( cipherText, cipherOff, tempInts, 0, 2 );
	decrypt( tempInts );
	spreadIntsToBytes( tempInts, 0, clearText, clearOff, 2 );
	}

    /// Decrypt a block of two ints.
    public void decrypt( int[] text )
	{
	int xl, xr, temp;
	int i;

	xr = text[0];
	xl = text[1];

	xr ^=  P[17];
	xl ^= F( xr ) ^ P[16];
	xr ^= F( xl ) ^ P[15];
	xl ^= F( xr ) ^ P[14];
	xr ^= F( xl ) ^ P[13];
	xl ^= F( xr ) ^ P[12];
	xr ^= F( xl ) ^ P[11];
	xl ^= F( xr ) ^ P[10];
	xr ^= F( xl ) ^ P[9];
	xl ^= F( xr ) ^ P[8];
	xr ^= F( xl ) ^ P[7];
	xl ^= F( xr ) ^ P[6];
	xr ^= F( xl ) ^ P[5];
	xl ^= F( xr ) ^ P[4];
	xr ^= F( xl ) ^ P[3];
	xl ^= F( xr ) ^ P[2];
	xr ^= F( xl ) ^ P[1];
	xl ^= P[0];

	text[0] = xl;
	text[1] = xr;
	}

    private int F( int x )
	{
	int a, b, c, d;
	d = x & 0x00FF;
	x >>= 8;
	c = x & 0x00FF;
	x >>= 8;
	b = x & 0x00FF;
	x >>= 8;
	a = x & 0x00FF;
	return ( ( S[0][a] + S[1][b] ) ^ S[2][c] ) + S[3][d];
	}


    /// Test routine.
    public static void main( String[] args )
	{
	byte[] cipherText = new byte[8];
	byte[] decipherText = new byte[8];

	BlockCipher bf1 = new BlowfishCipher( "abcdefghijklmnopqrstuvwxyz" );
	byte[] clearText1 = {
	    (byte) 0x42, (byte) 0x4c, (byte) 0x4f, (byte) 0x57,
	    (byte) 0x46, (byte) 0x49, (byte) 0x53, (byte) 0x48 };
	byte[] desiredText1 = {
	    (byte) 0x32, (byte) 0x4e, (byte) 0xd0, (byte) 0xfe,
	    (byte) 0xf4, (byte) 0x13, (byte) 0xa2, (byte) 0x03 };
	System.out.println( "cleartext: " + toStringBlock( clearText1 ) );
	bf1.encrypt( clearText1, cipherText );
	System.out.println( "encrypted: " + toStringBlock( cipherText ) );
	System.out.println( "desired:   " + toStringBlock( desiredText1 ) );
	bf1.decrypt( cipherText, decipherText );
	System.out.println( "decrypted: " + toStringBlock( decipherText ) );

	System.out.println();

	BlockCipher bf2 = new BlowfishCipher( "Who is John Galt?" );
	byte[] clearText2 = {
	    (byte) 0xfe, (byte) 0xdc, (byte) 0xba, (byte) 0x98,
	    (byte) 0x76, (byte) 0x54, (byte) 0x32, (byte) 0x10 };
	byte[] desiredText2 = {
	    (byte) 0xcc, (byte) 0x91, (byte) 0x73, (byte) 0x2b,
	    (byte) 0x80, (byte) 0x22, (byte) 0xf6, (byte) 0x84 };
	System.out.println( "cleartext: " + toStringBlock( clearText2 ) );
	bf2.encrypt( clearText2, cipherText );
	System.out.println( "encrypted: " + toStringBlock( cipherText ) );
	System.out.println( "desired:   " + toStringBlock( desiredText2 ) );
	bf2.decrypt( cipherText, decipherText );
	System.out.println( "decrypted: " + toStringBlock( decipherText ) );
	}


    // Initialization data.

    private static final int[] Pinit = {
	0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
	0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
	0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
	0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
	0x9216d5d9, 0x8979fb1b
	};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -