分享
 
 
 

enoeht的Java源码系列(5)--字符串加解密

王朝java/jsp·作者佚名  2006-01-30
窄屏简体版  字體: |||超大  

这一篇的内容是一个简单的对字符串加解密的类:

Then call its encrypt or decrypt method with an authenticator byte array (the parameter Auth which is a 16 octet byte array) and the data which is wanted to be encoded or decoded, the result is a byte array you wanted.

package org.kyle.util;

import java.security.*;

import java.io.*;

import java.text.*;

import java.util.*;

import java.math.*;

/* Call the shared secret S and the pseudo-random 128-bit

Authenticator RA.

Break the password into 16-octet chunks p1, p2,

etc. with the last one padded at the end with nulls to a 16-octet

boundary. Call the ciphertext blocks c(1), c(2), etc. We'll need

intermediate values b1, b2, etc.

b1 = MD5(S + RA) c(1) = p1 xor b1

b2 = MD5(S + c(1)) c(2) = p2 xor b2

. .

. .

. .

bi = MD5(S + c(i-1)) c(i) = pi xor bi

The String will contain c(1)+c(2)+...+c(i) where + denotes

concatenation.

On receipt, the process is reversed to yield the original

password.

*/

public class Cryptology

{

/** hidden secret data for encryption and decryption. */

private byte[] m_secret;

/** default secret length. */

private int m_defaultSecretLength = 256;

/**

* Default constructor to create object with default hidden secret.

*/

public Cryptology()

{

m_secret = createSecret( m_defaultSecretLength, normalize( getClass().getName() ) );

}

/**

* Allow to use user desired hidden secret to instantiate this object.

* @param specSecret the user desired hidden secret string.

* @param secretLen the length of secret in bytes.

*/

public Cryptology( String specSecret, int secretLen )

{

if ( specSecret == null )

specSecret = getClass().getName();

m_secret = createSecret( secretLen, normalize( specSecret ) );

}

/**

* Set a new Shared Secret for encryption and decryption.

* @param newSecret byte[] the new shared secret.

*/

public void setSecret( byte[] newSecret )

{

m_secret = newSecret;

}

/**

* Set a string for shared secret.

*/

public void setSecret( String theSecret )

{

m_secret = normalize( theSecret );

}

public byte[] getSecret()

{

return m_secret;

}

/**

Encrypting the rawData with random auth value.

*/

public byte[] encrypt(byte[] rawData, byte[] auth)

{

//if no secret or no authenticator data, don't encrypt the rawData.

if ( rawData == null ||

auth == null ||

auth.length != 16 ||

m_secret == null )

return rawData;

ArrayList cBlocks = getCipherBlocks( getChunks( rawData ), auth, true );

return concatChunks( cBlocks );

}

/**

Decoding the encoded data ( encData ) with given authenticator array ( auth ). The result is the byte array of plain value.

*/

public byte[] decrypt(byte[] encData, byte[] auth)

{

//if no secret or no authenticator data, don't decrypt the encData.

if ( encData == null ||

auth == null ||

auth.length != 16 ||

m_secret == null )

return encData;

ArrayList cBlocks = getCipherBlocks( getChunks( encData ), auth, false );

return concatChunks( cBlocks );

}

/**

* Data to be encrypted should be normalized to multiple 16 octets first.

* Origin string should be encoded to bytes in UTF-8. If UTF-8 not supported, * null will be returned.

*/

public static byte[] normalize( String wData )

{

try

{

byte oData[] = wData.getBytes("UTF-8");

//return bNormalize( oData );

return oData;

}

catch( UnsupportedEncodingException uee )

{

//Debug.println( new DbgMsg( uee, 3 ) );

Debug.warning("normalize UnsupportedEncodingException in Class Cryptology");

}

return null;

}

/**

* Get the UTF-8 encoded string of a decrypted byte array.

* @param oData byte array which was decrypted from an encrypted byte array.

* @return String encoded in UTF-8. If oData length is zero,

* empty string returned, if UTF-8 not supported, null returned.

*/

public static String rNormalize( byte oData[] )

{

int wdLen = oData.length;

//Debug.println("raw data length: " + wdLen );

if ( wdLen == 0 ) return "";

try

{

return new String( oData, "UTF-8" );

}

catch(UnsupportedEncodingException uee)

{

Debug.warning("normalize UnsupportedEncodingException in Class Cryptology");

}

return null;

}

private byte[] concatChunks( ArrayList chunks )

{

if ( chunks == null ) return new byte[0];

ByteArrayOutputStream baos = new ByteArrayOutputStream();

for( int i = 0; i < chunks.size(); i ++ )

{

BigInteger bgInt = (BigInteger)chunks.get( i );

byte[] cBytes = bgInt.toByteArray();

baos.write( cBytes , 0, cBytes.length );

}

return baos.toByteArray();

}

//////////////////////////////////////////////////////////////

private ArrayList getCipherBlocks( ArrayList pChunks, byte[] raBytes, boolean cipher)

{

if ( m_secret == null || raBytes == null || pChunks == null ) return null;

byte[] ss = new byte[ m_secret.length ];

System.arraycopy(m_secret, 0, ss, 0, m_secret.length );

Iterator iPs = pChunks.iterator();

ArrayList cipherBlocks = new ArrayList( pChunks.size() );

BigInteger bi = getIntMediValue( ss, raBytes );

String inter = "intermedium integer: " + bi.intValue() + "\n" ;

String ciph = "";

while( iPs.hasNext() )

{

BigInteger pi = (BigInteger)iPs.next();

BigInteger ci = cipherBlock( pi, bi );

//error occurred, invalid password not necessary to be creatDebug.println("intermedium integer: " + bi.intValue() );ed.

if ( ci == null ) return null;

cipherBlocks.add( ci );

//ciph += "Created ciphered integer: " + ci.intValue() + "(bitLen:" + ci.bitLength() + ")\n";

if ( cipher )

bi = getIntMediValue( ss, ci.toByteArray() );

else

bi = getIntMediValue( ss, pi.toByteArray() );

//inter += "intermedium integer: " +( bi == null ? "null" : bi.intValue() + "(bitLen:" + bi.bitLength() + ")\n") ;

}

//Debug.println( new DbgMsg( inter, Debug.TRACE_IN ) );

//Debug.println( new DbgMsg( ciph, Debug.TRACE_IN ) );

return cipherBlocks;

}

private ArrayList getChunks( byte[] rawPwd )

{

if ( rawPwd == null ) return null;

int chunkCnt = (rawPwd.length + 15) / 16 ;

ArrayList chunks = new ArrayList( chunkCnt );

ByteArrayInputStream bais = new ByteArrayInputStream( rawPwd );

String msg = "";

for( int i = 0; i < chunkCnt; i++)

{

int len = bais.available();

if ( len > 16 ) len = 16;

byte[] chunk = new byte[ 16 ];

int bitLen = bais.read(chunk, 0, len );

//Debug.println("read bytes:" + bitLen +"; value:" + (new String( chunk ) ) );

if ( bitLen != -1 )

{

if ( len < 16 )

Arrays.fill( chunk, len, 15, (byte)0x00 );

BigInteger bi = new BigInteger( chunk );

chunks.add( bi );

}

}

//Debug.println( new DbgMsg( msg, Debug.TRACE_IN ) );

return chunks;

}

private BigInteger getIntMediValue(byte[] secret, byte[] raOrct )

{

if ( secret == null || raOrct == null || raOrct.length < 16 ) return null;

try

{

MessageDigest msgDgt = MessageDigest.getInstance("MD5");

byte[] input = new byte[ secret.length + raOrct.length ];

System.arraycopy(secret,0, input, 0, secret.length );

System.arraycopy(raOrct,0, input, secret.length, raOrct.length );

return new BigInteger( msgDgt.digest( input ) );

}

catch(NoSuchAlgorithmException nsae)

{

Debug.warning("normalize NoSuchAlgorithmException in Class Cryptology");

}

return null;

}

private BigInteger cipherBlock( BigInteger pi, BigInteger bi )

{

if ( pi == null || bi == null ) return null;

BigInteger cpbk = pi.xor( bi );

return cpbk;

}

/**

* If a password's length is less than 16, it will be padded

* to 16 with null. This makes its decrypted value have a

* invalid tail encoded in the nulls. This method will compare

* the string from decrypted bytes and stored origin string

* with the padding nulls tail considered.

* @param decryptedPwd the restored password string

* created from decrypted bytes.

* @param storedPwd the origin password stored

* for authentication.

* @return boolean true if and only if the decryptedPwd

* is started with storedPwd and appended

* by a serias of nulls or none.

*/

public static boolean equals( String decryptedPwd, String storedPwd )

{

try

{

if ( decryptedPwd.length() < storedPwd.length() ) return false;

byte[] dp = decryptedPwd.getBytes("ISO-8859-1");

byte[] sp = storedPwd.getBytes("ISO-8859-1");

if ( dp.length > sp.length )

{

int tLen = dp.length - sp.length;

byte [] spe = new byte[ tLen ];

Arrays.fill( spe, (byte)0x00 );

ByteArrayOutputStream baos = new ByteArrayOutputStream();

baos.write( sp );

baos.write( spe );

sp = baos.toByteArray();

}

return Arrays.equals( dp, sp );

}

catch( Exception e )

{

Debug.warning("normalize Exception in Class Cryptology");

}

return false;

}

private byte[] createSecret( int len, byte[] seed )

{

if ( seed == null )

{

seed = normalize( getClass().getName() );

}

if ( len <= 0 ) len = m_defaultSecretLength;

SecureRandom scRdm = new SecureRandom( seed );

byte[] aSec = new byte[ len ];

scRdm.nextBytes( aSec );

return aSec;

}

/**

* If a password's length is less than 16, it will be padded

* to 16 with null. This makes its decrypted value have a

* invalid tail encoded in the nulls. This method will cut the

* invalid tail and return the "CLEAR" data.

* @param data byte[] the origin decrypted byte array.

* @return byte[] bytes from data without the nulls tail.

* if any exception occurred, null returned.

*/

public static byte[] getClearData( byte[] data)

{

try

{

StringBuffer sb = new StringBuffer();

sb.append( new String(data, "ISO-8859-1") );

sb.reverse();

BigInteger rBi = new BigInteger( sb.toString().getBytes("ISO-8859-1") );

sb = new StringBuffer();

sb.append( new String( rBi.toByteArray(), "ISO-8859-1") );

sb.reverse();

return sb.toString().getBytes("ISO-8859-1") ;

}

catch(Exception e)

{

Debug.warning("normalize Exception in Class Cryptology");

}

return null;

}

/*

//for test

public static void main( String argv[] )

{

Cryptology crypto = new Cryptology();

if ( argv.length < 1 )

{

System.exit(0);

}

//Store default secret to file default.sec

try

{

FileOutputStream fos = new FileOutputStream("default.sec");

fos.write( crypto.getSecret() );

fos.close();

}

catch(IOException e){}

if ( argv.length == 2 )

crypto.setSecret( argv[1] );

SecureRandom scRdm = new SecureRandom( SecureRandom.getSeed( 16 ) );

byte[] auth = new byte[16];

scRdm.nextBytes( auth );

String rawStr = argv[0];

System.out.println("Origin String: " + rawStr );

byte[] scStr = crypto.normalize( rawStr );

if ( scStr == null )

{

System.out.println(" Normalization of origin string failed.");

System.exit(0);

}

try

{

scStr = crypto.encrypt( scStr, auth );

System.out.println( "Encrypted string: " + crypto.rNormalize( scStr ) + "; bytesCount: " + scStr.length );

scStr = crypto.decrypt( scStr, auth );

System.out.println( "Decrypted string: " + crypto.rNormalize(scStr) );

System.out.println( "Cleared Decrypted password: " + ( new String( Cryptology.getClearData( scStr ) ) ) );

}

catch( Exception uee)

{}

}

*/

}

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有