All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.siisise.security.mac.XCBC Maven / Gradle / Ivy

/*
 * Copyright 2023 okome.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.siisise.security.mac;

import java.util.Arrays;
import net.siisise.io.Packet;
import net.siisise.io.PacketA;
import net.siisise.lang.Bin;
import net.siisise.security.block.Block;

/**
 * RFC 3566 AES-XCBC-MAC-96 MAC
 * XCBC-MAC-1
 * RFC 3664,4434 AES-XCBC-PRF-128 疑似乱数
 */
public class XCBC implements MAC {

    private final Block block;
    private MacCBC cbc;
    
    private byte[] k1;
    private byte[] k2;
    private byte[] k3;
    
    private Packet m;
    int outlen;
    
    /**
     * 
     * @param block AESなど暗号ブロック CBCは含まない
     * @param len 出力バイト長
     */
    public XCBC(Block block, int len) {
        this.block = block;
        this.outlen = len;
    }

    /**
     * 
     * @param block AES または出力サイズが決まっているBlock CBCは含まない
     */
    public XCBC(Block block) {
        this(block,(block.getBlockLength() + 7) / 8);
    }

    /**
     * 
     * @param key AES-XCBC-MAC-96では128bitのみ
     */
    @Override
    public void init(byte[] key) {
        block.init(key);
        int maclen = (block.getBlockLength() + 7) / 8;
        k1 = new byte[maclen];
        k2 = new byte[maclen];
        k3 = new byte[maclen];
        Arrays.fill(k1, (byte)0x01);
        Arrays.fill(k2, (byte)0x02);
        Arrays.fill(k3, (byte)0x03);
        init(block.encrypt(k1),block.encrypt(k2),block.encrypt(k3));
    }
    
    public void init(byte[]... keys) {
        k1 = keys[0];
        block.init(k1);
        k2 = keys[1];
        k3 = keys[2];
        m = new PacketA();
        cbc = new MacCBC(block);
    }

    @Override
    public void update(byte[] src, int offset, int length) {
        int mlen = m.size();
        if ( mlen > 0 && mlen + length > k2.length ) {
            byte[] t = new byte[k2.length];
            m.read(t);
            int blen = k2.length - mlen;
            System.arraycopy(src, offset, t, mlen, blen);
            offset += blen;
            length -= blen;
            cbc.update(t,0,k2.length);
        }
        if ( length > k2.length ) {
            int blen = (length - 1) / k2.length * k2.length;
            cbc.update(src, offset, blen);
            offset += blen;
            length -= blen;
        }
        m.write(src, offset, length);
}

    @Override
    public byte[] sign() {
        byte[] t = new byte[k2.length];
        if ( m.size() < k2.length ) { // 10* Padding
            m.write(0x80);
            m.read(t);
            Bin.xorl(t, k3);
        } else {
            m.read(t);
            Bin.xorl(t, k2);
        }
        cbc.update(t,0,t.length);
        t = cbc.vector();
        cbc = new MacCBC(block); // 次の初期化
        return Arrays.copyOf(t, outlen);
    }

    @Override
    public int getMacLength() {
        return outlen;
    }
    
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy