| /* |
| * Copyright 2015-2016 Rivoreo |
| * |
| * This program is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License as published by the |
| * Free Software Foundation, either version 2 of the License, or (at your |
| * option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| * more details. |
| */ |
| |
| package org.rivoreo.crypto; |
| |
| public class ECIES_ChaCha20 extends ECIES implements ECIES.NonceListener { |
| public ECIES_ChaCha20(SECTDomainParameters dp, int chacha20_key_size) { |
| super(dp); |
| if(chacha20_key_size != 16 && chacha20_key_size != 32) { |
| throw new IllegalArgumentException("chacha20_key_size can only be 16 or 32"); |
| } |
| key_size = chacha20_key_size; |
| nonce = new byte[8]; |
| set_symmetric_crypt_nonce_listener(this, 8); |
| } |
| public ECIES_ChaCha20(SECTDomainParameters dp) { |
| this(dp, 32); |
| } |
| |
| private final int key_size; |
| private final byte[] nonce; |
| |
| public void set_nonce(byte[] nonce) { |
| if(nonce.length < 8) throw new IllegalArgumentException("nonce.length < 8"); |
| for(int i=0; i<8; i++) this.nonce[i] = nonce[i]; |
| } |
| |
| protected int get_symmetric_key_bytes() { |
| return key_size; |
| } |
| |
| protected void ctr_crypt(byte[] data, int len, final byte[] key) { |
| System.err.printf("method: org.rivoreo.crypto.ECIES_ChaCha20::ctr_crypt(byte[%d], %d, final byte[%d])\n", data.length, len, key.length); |
| ChaCha20 ctx = new ChaCha20(key, key_size, nonce); |
| ctx.encrypt(data, len); |
| } |
| |
| protected void cbc_mac(byte[] mac, final byte[] data, int len, final byte[] key) { |
| System.err.printf("method: org.rivoreo.crypto.ECIES_ChaCha20::cbc_mac(byte[%d], final byte[%d], %d, final byte[%d])\n", mac.length, data.length, len, key.length); |
| ChaCha20 ctx = new ChaCha20(key, key_size, nonce); |
| int blen, i, di = 0; |
| int_to_bytes(mac, 0, 0); |
| int_to_bytes(mac, 4, len); |
| ctx.encrypt(mac, ECIES_CHUNK_OVERHEAD); |
| while(len > 0) { |
| blen = Math.min(ECIES_CHUNK_OVERHEAD, len); |
| i = 0; |
| while(i < blen) mac[i++] ^= data[di++]; |
| ctx.encrypt(mac, ECIES_CHUNK_OVERHEAD); |
| len -= blen; |
| } |
| } |
| |
| protected void davies_meyer(byte[] out, final byte[] in, int ilen) { |
| System.err.printf("method: org.rivoreo.crypto.ECIES_ChaCha20::davies_meyer(byte[%d], final byte[%d], %d)\n", out.length, in.length, ilen); |
| debug_print_bytes(nonce, 8); |
| int i, offset = 0; |
| byte[] buffer = new byte[key_size / 2]; |
| ChaCha20 ctx; |
| for(i = 0; i < key_size / 2; i++) out[i] = 0; |
| while(ilen-- > 0) { |
| ctx = new ChaCha20(sub_byte_array(in, offset), key_size, nonce); |
| for(i = 0; i < buffer.length; i++) buffer[i] = out[i]; |
| ctx.encrypt(buffer, buffer.length); |
| debug_print_bytes(buffer, buffer.length); |
| for(i = 0; i < buffer.length; i++) out[i] ^= buffer[i]; |
| offset += key_size; |
| } |
| } |
| |
| } |