注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

古城风~~~

竹密无妨溪水过,天高不碍白云飞。这天下总有一份是属于我古城的天地!

 
 
 

日志

 
 

Rabbit流密码的Java实现  

2009-10-03 11:23:54|  分类: java/jsp |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

1. Rabbit流密码(Rabbit Stream Cipher)简介

    Rabbit流密码是由Cryptico公司(http://www.cryptico.com)设计的,密钥长度128位,

    最大加密消息长度为264 Bytes,即16 TB,若消息超过该长度,则需要更换密钥对剩下的消息进行处理。它是目前安全性较高,加/解密速度比较高效的流密码之一,在各种处理器平台上都有不凡的表现。

    详细资料:

    1.http://www.cryptico.com/Files/filer/rabbit_fse.pdf

    2.http://www.ietf.org/rfc/rfc4503.txt

    本文实现了该算法的java语言实现,仅供参考。

    2.  实现源码

    view plaincopy to clipboardprint?

    /**

    * The Java Implementation of Rabbit Stream Cipher

    * @author cnbragon

    * @email cnbragon_dot_163_dot_com

    * @date 2009/09/25

    * @note Not implemented IV scheme

    * @Reference:

    * 1.http://www.cryptico.com/Files/filer/rabbit_fse.pdf * 2.http://www.ietf.org/rfc/rfc4503.txt

    */

    class Rabbit

    {

    private int[] x = new int[8];

    private int[] c = new int[8];

    private int carry;

    public void Rabbit()

    {

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

    {

    x[i] = c[i] = 0;

    }

    carry = 0;

    }

    private int g_func(int x)

    {

    int a = x & 0xffff;

    int b = x >>> 16;

    int h =( ( ( ( a * a ) >>> 17 ) + ( a * b ) ) >>> 15 ) + b * b;

    int l = x * x;

    return h ^ l;

    }

    /**

    * @declaration 比较两个无符号整数的十六进制的大小,即作为无符号整数进行比较

    * @param x

    * @param y

    * @return 若(unsigned x) < (unsigned y),则返回1,否则返回0

    */

    private int compare(int x, int y)

    {

    long a = x;

    long b = y;

    a &= 0x00000000ffffffffl;

    b &= 0x00000000ffffffffl;

    return (a < b) ? 1 : 0;

    }

    private int rotL(int x, int y)

    {

    return ( x << y ) | ( x >>> (32 - y) );

    }

    private void next_state()

    {

    int[] g = new int[8];

    int[] c_old = new int[8];

    int i = 0;

    for( i = 0; i < 8; i++)

    {

    c_old[i] = c[i];

    }

    c[0] += 0x4d34d34d + carry;

c[1] += 0xd34d34d3 + compare(c[0], c_old[0]); c[2] += 0x34d34d34 + compare(c[1], c_old[1]); c[3] += 0x4d34d34d + compare(c[2], c_old[2]); c[4] += 0xd34d34d3 + compare(c[3], c_old[3]); c[5] += 0x34d34d34 + compare(c[4], c_old[4]); c[6] += 0x4d34d34d + compare(c[5], c_old[5]); c[7] += 0xd34d34d3 + compare(c[6], c_old[6]); carry = compare(c[7], c_old[7]);

    for( i = 0; i < 8; i++)

    {

    g[i] = g_func(x[i] + c[i]);

    }

    x[0] = g[0] + rotL(g[7], 16) + rotL(g[6], 16); x[1] = g[1] + rotL(g[0], 8 ) + g[7]; x[2] = g[2] + rotL(g[1], 16) + rotL(g[0], 16); x[3] = g[3] + rotL(g[2], 8 ) + g[1]; x[4] = g[4] + rotL(g[3], 16) + rotL(g[2], 16); x[5] = g[5] + rotL(g[4], 8 ) + g[3]; x[6] = g[6] + rotL(g[5], 16) + rotL(g[4], 16); x[7] = g[7] + rotL(g[6], 8 ) + g[5];

    }

    /**

    * @declaration 将一个字节数组转化为整数,采用Big-Endian格式进行解析

    * @param a待转化的字节数组

    * @param i字节数组的起始索引

    * @return转化后的整数

    */

    public static int os2ip(byte[] a, int i)

    {

    int x0 = a[i + 3] & 0x000000ff;

    int x1 = a[i + 2] << 8 & 0x0000ff00;

    int x2 = a[i + 1] << 16 & 0x00ff0000;

    int x3 = a[i] << 24 & 0xff000000;

    return x0 | x1 | x2 | x3;

    }

    /**

    * @declaration 将整数x转化为4字节数组,采用Big-Endian格式进行解析

    * @param x待转化的整数x

    * @return 解析后的字节数组,长度为4

    */

    public static byte[] i2osp(int x)

    {

    byte[] s = new byte[4];

    s[3] = (byte)( x & 0x000000ff );

    s[2] = (byte)( ( x & 0x0000ff00 ) >>> 8 );

    s[1] = (byte)( ( x & 0x00ff0000 ) >>> 16 );

    s[0] = (byte)( ( x & 0xff000000 ) >>> 24 );

    return s;

    }

    /**

    * @declaration密钥初始化函数

    * @param p_key 长度为128位的密钥数组,若密钥长度小于128位,

    *则必须在填充后再调用该函数

    */

    public void keySetup(byte[] p_key)

    {

    int k0, k1, k2, k3, i;

    k0 = os2ip(p_key, 12); k1 = os2ip(p_key, 8); k2 = os2ip(p_key, 4); k3 = os2ip(p_key, 0);

    x[0] = k0;

    x[2] = k1;

    x[4] = k2;

    x[6] = k3;

    x[1] = ( k3 << 16 ) | ( k2 >>> 16 );

    x[3] = ( k0 << 16 ) | ( k3 >>> 16 );

    x[5] = ( k1 << 16 ) | ( k0 >>> 16 );

    x[7] = ( k2 << 16 ) | ( k1 >>> 16 );

    c[0] = rotL(k2, 16); c[2] = rotL(k3, 16); c[4] = rotL(k0, 16); c[6] = rotL(k1, 16);

    c[1] = (k0 & 0xffff0000) | (k1 & 0x0000ffff);

    c[3] = (k1 & 0xffff0000) | (k2 & 0x0000ffff);

    c[5] = (k2 & 0xffff0000) | (k3 & 0x0000ffff);

    c[7] = (k3 & 0xffff0000) | (k0 & 0x0000ffff);

    carry = 0;

    for( i = 0; i < 4; i++)

    {

    next_state();

    }

    for( i = 0; i < 8; i++)

    {

    c[ (i + 4) & 7 ] ^= x[i];

    }

    }

    /**

    * @declaration 该函数用于生成128位随机密钥,用于直接和明文进行异或处理

    * @param p_dest产生的128位随机密钥

    * @param data_size 需要产生的随机密钥数量,必须是16的倍数

    */

    public void getS(byte[] p_dest, long data_size)

    {

    int i, j, m;

    int[] k = new int[4];

    byte[] t = new byte[4];

    for( i = 0; i < data_size; i+=16)

    {

    next_state();

    k[0] = x[0] ^ ( x[5] >>> 16 ) ^ ( x[3] << 16 );

    k[1] = x[2] ^ ( x[7] >>> 16 ) ^ ( x[5] << 16 );

    k[2] = x[4] ^ ( x[1] >>> 16 ) ^ ( x[7] << 16 );

    k[3] = x[6] ^ ( x[3] >>> 16 ) ^ ( x[1] << 16 );

    for( j = 0; j < 4; j++)

    {

    t = i2osp(k[j]);

    for( m = 0; m < 4; m++)

    {

    p_dest[ j * 4 + m ] = t[m];

    }

    }

    }

    }

/**

    * @declaration加密和解密函数

    * @param p_src 需要加密或解密的消息,其长度必须是16的倍数,以字节为单位,*               若不是16的倍数,则需要在调用该函数前进行填充,一般填充值

    *为0的字节

    * @param p_dest 加密或解密的结果,其长度必须是16的倍数,以字节为单位

    *并且长度必须大于等于p_src的长度

    * @param data_size 需要处理的消息的长度,必须是16的倍数,以字节为单位

    *其值为p_src的长度

    */

    public void cipher(byte[] p_src, byte[] p_dest, long data_size)

    {

    int i, j, m;

    int[] k = new int[4];

    byte[] t = new byte[4];

    for( i = 0; i < data_size; i+=16)

    {

    next_state();

    k[0] = os2ip(p_src, i * 16 + 0) ^ x[0] ^ ( x[5] >>> 16 ) ^ ( x[3] << 16 ); k[1] = os2ip(p_src, i * 16 + 4) ^ x[2] ^ ( x[7] >>> 16 ) ^ ( x[5] << 16 ); k[2] = os2ip(p_src, i * 16 + 8) ^ x[4] ^ ( x[1] >>> 16 ) ^ ( x[7] << 16 ); k[3] = os2ip(p_src, i * 16 + 12) ^ x[6] ^ ( x[3] >>> 16 ) ^ ( x[1] << 16 );

    for( j = 0; j < 4; j++)

    {

    t = i2osp(k[j]);

    for( m = 0; m < 4; m++)

    {

    p_dest[ i * 16 + j * 4 + m ] = t[m];

    }

    }

    }

    }

    }

    public class Main {

    public static void main(String[] args) {

    /**

    * 定义测试密钥key,需要注意的是,由于java没有unsigned类型,* 所以需要对大于等于0x80的字节进行类型转换,

    *比较方便的办法是都加上(byte)

    */

    byte[] key = {

    (byte)0xa0, (byte)0x33, (byte)0xd6, (byte)0x78, (byte)0x6b, (byte)0x05, (byte)0x14, (byte)0xac, (byte)0xfc, (byte)0x3d, (byte)0x8e, (byte)0x2d, (byte)0x6a, (byte)0x2c, (byte)0x27, (byte)0x1d

    };

    /**

    * 定义待加密的消息message,密文ciphertext,并初始化为0

    */

    byte[] message = new byte[16];

    byte[] ciphertext = new byte[16];

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

    {

    message[i] = (byte)i;

    ciphertext[i] = 0;

    }

    /**

    *调用Rabbit流密码进行加密

    */

    Rabbit rtest = new Rabbit();

    /*

    *初始化密钥

    */

    rtest.keySetup(key);

    /*

    *加密

    */

    rtest.cipher(message, ciphertext, 16);

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

    {

    System.out.printf("%02x ", ciphertext[i]);

    }

    System.out.println();

    /**

    *调用Rabbit流密码进行解密

    */

    Rabbit rtest2 = new Rabbit();

    /*

    *初始化密钥

    */

    rtest2.keySetup(key);

    byte[] szT = new byte[16];

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

    {

    szT[i] = 0;

    }

    /*

    *解密

    */

    rtest2.cipher(ciphertext, szT, 16);

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

    {

    System.out.printf("%02x ", szT[i]);

    }

    System.out.println();

    }

    }

 

资料来源:http://java.chinaitlab.com/advance/794462_3.html

  评论这张
 
阅读(532)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017