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

net.siisise.security.key.HKDF Maven / Gradle / Ivy

/*
 * Copyright 2023 Siisise Net.
 *
 * 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.key;

import java.security.MessageDigest;
import net.siisise.security.PacketS;
import net.siisise.security.mac.HMAC;
import net.siisise.security.mac.MAC;

/**
 * 鍵導出関数. Key Derivation Function KDF.
 * FIPS 198-1 HMAC-based KDF
 * RFC 5869 HKDF.
 * RFC 6234 US Secure Hash Algorithms (SHA and SHA-based HMAC and HKDF)
 *   7.2. HKDF
 * RFC 8619 HKDFのOID.
 *
 */
public class HKDF implements KDF {

    private final MAC mac;
    byte[] salt;
    byte[] info;
    int dkLen;

    /**
     * 規格ではSHAアルゴリズムを指定する。
     * その他も指定可能。
     * SHAのパラメータはなし
     * @param sha SHA-256, SHA-384, SHA-512 くらいを想定されているらしい
     */
    public HKDF(MessageDigest sha) {
        mac = new HMAC(sha);
    }

    /**
     * ハッシュベースでなくてもMACであれば利用可能?
     * @param mac 繰り返し利用できること
     */
    public HKDF(MAC mac) {
        this.mac = mac;
    }

    /**
     * 
     * @param salt 塩 (HMAC鍵) null可
     * @param info 付加 null可 saltっぽいもの
     * @param dkLen 出力派生鍵長
     */
    public void init(byte[] salt, byte[] info, int dkLen) {
        this.salt = salt;
        this.info = info;
        this.dkLen = dkLen;
    }

    /**
     *
     * @param salt 塩 (1段目のHMAC鍵) HMACの長さ推奨 null可
     * @param ikm 秘密鍵
     * @param info 付加 null可 saltっぽいもの
     * @param length L リクエスト鍵長 (HMACの255倍まで)
     * @return OKM output keying maerial (of L octets)
     */
    public byte[] hkdf(byte[] salt, byte[] ikm, byte[] info, int length) {
        byte[] prk = extract(salt, ikm);
        return expand(prk, info, length);
    }
    
    @Override
    public byte[] kdf(byte[] ikm) {
        return hkdf(salt, ikm, info, dkLen);
    }

    /**
     * Extract
     * Section 2.2.
     * HMAC 1回目 HMAC(salt).doFinal(ikm)
     * @param salt 塩 (HMAC鍵) HMACの長さ推奨 null可
     * @param ikm 秘密鍵
     * @return prk 疑似ランダム鍵
     */
    byte[] extract(byte[] salt, byte[] ikm) {
        if (salt == null) {
            salt = new byte[0];
        }
        mac.init(salt);
        return mac.doFinal(ikm);
    }

    /**
     * 鍵長になるまで繰り返し.
     * 
     * @param prk PRK 中間鍵
     * @param info 付加 saltっぽいもの
     * @param length L 鍵長 byte
     * @return OKM output keying maerial (of L octets)
     */
    private byte[] expand(byte[] prk, byte[] info, int length) {
        int l = mac.getMacLength();
        int n = ((length + l - 1) / l);
        if (info == null) {
            info = new byte[0];
        }
        PacketS pt = new PacketS();
        byte[] t = new byte[0];
        mac.init(prk);
        byte[] d = new byte[1];
        for (int i = 1; i <= n; i++) {
            mac.update(t);
            mac.update(info);
            d[0] = (byte) i;
            t = mac.doFinal(d);
            pt.write(t);
        }
        byte[] r = new byte[length];
        pt.read(r);
        return r;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy