java 算法移植_Java:Chacha20算法(从openssl移植)

这篇博客介绍了如何将Chacha20算法从OpenSSL移植到Java平台,提供了具体的加密和解密示例,包括关键的`Chacha20`类及核心的`cryptoCounter32`方法。通过示例代码展示了如何使用该算法进行数据的加解密操作。
摘要由CSDN通过智能技术生成

使用示例

String str = "hello world";

int key[] = {-123,-456,789,123,456,7890,456,456};

int noc[] = {-123,-456,789,123};

byte[] encryptData = Chacha20.crytpoCounter32(str.getBytes(),key,noc);

byte[] decryptData = Chacha20.crytpoCounter32(encryptData,key,noc);

String str2 = new String(decryptData);

boolean equal = str.equals(str2);

具体代码

package com.zxs.zl;

/*

* Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.

*

* Licensed under the Apache License 2.0 (the "License"). You may not use

* this file except in compliance with the License. You can obtain a copy

* in the file LICENSE in the source distribution or at

* https://www.openssl.org/source/license.html

*/

public class Chacha20 {

/*

* ChaCha20_ctr32 encrypts |len| bytes from |inp| with the given key and

* nonce and writes the result to |out|, which may be equal to |inp|.

* The |key| is not 32 bytes of verbatim key material though, but the

* said material collected into 8 32-bit elements array in host byte

* order. Same approach applies to nonce: the |counter| argument is

* pointer to concatenated nonce and counter values collected into 4

* 32-bit elements. This, passing crypto material collected into 32-bit

* elements as opposite to passing verbatim byte vectors, is chosen for

* efficiency in multi-call scenarios.

*/

/**

* function same ,encrypt and decrypt

* @param inp source data (encrypt data or decrypt data)

* @param key int[8] array

* @param counter int[4] array

* @return decrypt data or encrypt data ; see inp param.

*/

public static byte[] crytpoCounter32(byte[] inp, int[] key,int[] counter)

{

byte[] out = new byte[inp.length];

int[] input = new int[16];

byte[] buf = new byte[64];

int todo, i;

/* sigma constant "expand 32-byte k" in little-endian encoding */

input[0] = ((int)'e') | ((int)'x'<<8) | ((int)'p'<<16) | ((int)'a'<<24);

input[1] = ((int)'n') | ((int)'d'<<8) | ((int)' '<<16) | ((int)'3'<<24);

input[2] = ((int)'2') | ((int)'-'<<8) | ((int)'b'<<16) | ((int)'y'<<24);

input[3] = ((int)'t') | ((int)'e'<<8) | ((int)' '<<16) | ((int)'k'<<24);

input[4] = key[0];

input[5] = key[1];

input[6] = key[2];

input[7] = key[3];

input[8] = key[4];

input[9] = key[5];

input[10] = key[6];

input[11] = key[7];

input[12] = counter[0];

input[13] = counter[1];

input[14] = counter[2];

input[15] = counter[3];

int len = inp.length;

int offset = 0;

while (len > 0) {

todo = 64;// equal to buf.length;

if (len < todo)

todo = len;

chacha20_core(buf, input);

for (i = 0; i < todo; i++){

out[i+offset] = (byte) (inp[i+offset] ^ buf[i]);

}

offset += todo;

len -= todo;

/*

* Advance 32-bit counter. Note that as subroutine is so to

* say nonce-agnostic, this limited counter width doesn't

* prevent caller from implementing wider counter. It would

* simply take two calls split on counter overflow...

*/

input[12]++;

}

return out;

}

/* chacha_core performs 20 rounds of ChaCha on the input words in

* |input| and writes the 64 output bytes to |output|. */

private static void chacha20_core(byte[] output, int[] input)

{

//output byte[64]

long[] x = new long[16];

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

x[i] = (input[i] & 0xFFFFFFFFL );

}

for (int i = 20; i > 0; i -= 2) {

QUARTERROUND(x,0, 4, 8, 12);

QUARTERROUND(x,1, 5, 9, 13);

QUARTERROUND(x,2, 6, 10, 14);

QUARTERROUND(x,3, 7, 11, 15);

QUARTERROUND(x,0, 5, 10, 15);

QUARTERROUND(x,1, 6, 11, 12);

QUARTERROUND(x,2, 7, 8, 13);

QUARTERROUND(x,3, 4, 9, 14);

}

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

long v = (x[i] + input[i]) & 0xFFFFFFFFL;

output[i<<2] = (byte) (v & 0xFF);

output[(i<<2) + 1] = (byte) ((v>>8) & 0xFF);

output[(i<<2) + 2] = (byte) ((v>>16) & 0xFF);

output[(i<<2) + 3] = (byte) ((v>>24) & 0xFF);

}

}

/* QUARTERROUND updates a, b, c, d with a ChaCha "quarter" round. */

private static void QUARTERROUND(long[]x, int a,int b,int c,int d){

x[a] = (x[a] + x[b]) & 0xFFFFFFFFL;

x[d] = ROTATE((x[d] ^ x[a]),16) & 0xFFFFFFFFL;

x[c] = (x[c] + x[d]) & 0xFFFFFFFFL;

x[b] = ROTATE((x[b] ^ x[c]),12) & 0xFFFFFFFFL;

x[a] = (x[a] + x[b]) & 0xFFFFFFFFL;

x[d] = ROTATE((x[d] ^ x[a]), 8) & 0xFFFFFFFFL;

x[c] = (x[c] + x[d]) & 0xFFFFFFFFL;

x[b] = ROTATE((x[b] ^ x[c]), 7) & 0xFFFFFFFFL;

}

private static long ROTATE(long v,int n)

{

v = v & 0xFFFFFFFFL;

return (((v) << (n)) | ((v) >> (32 - (n))));

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值