itlgl / note

使用github的issues功能记录日常的笔记
http://itlgl.com/note
5 stars 2 forks source link

java SHA3算法实现 #11

Open itlgl opened 6 years ago

itlgl commented 6 years ago

SHA3算法即为Keccak算法

贴一张维基百科的图 sha

BouncyCastle中的实现

BouncyCastle中实现了SHA3算法家族的所有实现,对应实现在org.bouncycastle.crypto.digests.SHA3Digestorg.bouncycastle.crypto.digests.SHAKEDigest中,(但是现在还没有搞清楚SHAKE算法的调用方法,维基百科上写的SHAKE算法输出长度不固定,所以调用的示例都是SHAKE128("", 256) 7f9c2ba4e88f827d616045507605853ed73b8093f6efbc88eb1a6eacfa66ef26这种,貌似传了一个最大长度?),示例代码:

// SHA3家族:SHA3-224,SHA3-256,SHA3-384,SHA3-512,SHAKE128,SHAKE256
private static final Digest _SHA3_224Digest = new SHA3Digest(224);
private static final Digest _SHA3_256Digest = new SHA3Digest(256);
private static final Digest _SHA3_384Digest = new SHA3Digest(384);
private static final Digest _SHA3_512Digest = new SHA3Digest(512);
// private static final Digest _SHA3_SHAKE128Digest = new SHAKEDigest(128);
// private static final Digest _SHA3_SHAKE256Digest = new SHAKEDigest(256);

private static byte[] doDigest(Digest digest, byte[] src) {
    digest.reset();
    byte[] result = new byte[digest.getDigestSize()];
    digest.update(src, 0, src.length);
    digest.doFinal(result, 0);
    return result;
}

public static byte[] sha3_224(byte[] src) {
    return doDigest(_SHA3_224Digest, src);
}

public static byte[] sha3_256(byte[] src) {
    return doDigest(_SHA3_256Digest, src);
}

public static byte[] sha3_384(byte[] src) {
    return doDigest(_SHA3_384Digest, src);
}

public static byte[] sha3_512(byte[] src) {
    return doDigest(_SHA3_512Digest, src);
}

以太坊中的实现(Keccak256,和sha3哈希结果不同)

在以太坊的java实现代码中,有sha3算法的实现:https://github.com/ethereum/ethereumj/blob/develop/ethereumj-core/src/main/java/org/ethereum/crypto/cryptohash/Keccak256.java

注意:Keccak256算法和sha3算法略有区别,结果是不一样的。以太坊使用Keccak256算法来进行HASH运算,而不是sha3算法。

在代码中,作者将算法实现加入到SpongyCastle的算法集中:

// 代码位于:org.ethereum.crypto.jce.SpongyCastleProvider
private static final Provider INSTANCE;
static{
    Provider p = Security.getProvider("SC");

    INSTANCE = (p != null) ? p : new BouncyCastleProvider();

    INSTANCE.put("MessageDigest.ETH-KECCAK-256", "org.ethereum.crypto.cryptohash.Keccak256");
    INSTANCE.put("MessageDigest.ETH-KECCAK-512", "org.ethereum.crypto.cryptohash.Keccak512");
}

而后调用sha3算法时,只需要在Digest算法中填写"ETH-KECCAK-256"串即可调用sha3算法:

// 代码位于:org.ethereum.crypto.HashUtil,为了方便查看,将方法中的变量直接替换为字符串
public static byte[] sha3(byte[] input) {
    MessageDigest digest;
    try {
        digest = MessageDigest.getInstance("ETH-KECCAK-256", “SC”);
        digest.update(input);
        return digest.digest();
    } catch (NoSuchAlgorithmException e) {
        LOG.error("Can't find such algorithm", e);
        throw new RuntimeException(e);
    }

}