gpt4 book ai didi

java - 如何在纯 Java 中创建或打开与 libsodium 兼容的密封盒

转载 作者:行者123 更新时间:2023-11-29 04:34:11 25 4
gpt4 key购买 nike

libsodium 提供了一个 API 来创建或打开此处记录的密封盒 https://download.libsodium.org/doc/public-key_cryptography/sealed_boxes.html

我怎样才能在纯 Java 中实现相同的目的,以便允许我打开一个由 libsodium 创建的盒子或创建一个 libsodium 可以打开的盒子?

最佳答案

以下示例代码可以创建并打开一个 libsodium 密封盒。

它需要来自 https://github.com/InstantWebP2P/tweetnacl-java 的 TweetNaclFast和一个 Blake2b 哈希实现,例如来自 https://github.com/alphazero/Blake2b 的那个

import java.security.GeneralSecurityException;
import java.util.Arrays;
import ove.crypto.digest.Blake2b;
import com.iwebpp.crypto.TweetNaclFast;


/**
* Example how to open sealed boxes in pure java (libsodium sealed boxes according to
* https://download.libsodium.org/doc/public-key_cryptography/sealed_boxes.html)
*
* Has a dependency on TweetNaclFast and Blake2B, for example
*
* https://github.com/alphazero/Blake2b
* and
* https://github.com/InstantWebP2P/tweetnacl-java
*
*/
public class SealedBoxUtility {


public static final int crypto_box_NONCEBYTES = 24;
public static final int crypto_box_PUBLICKEYBYTES = 32;
public static final int crypto_box_MACBYTES = 16;
public static final int crypto_box_SEALBYTES = (crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES);

// libsodium
// int crypto_box_seal(unsigned char *c, const unsigned char *m,
// unsigned long long mlen, const unsigned char *pk);


/**
* Encrypt in a sealed box
*
* @param clearText clear text
* @param receiverPubKey receiver public key
* @return encrypted message
* @throws GeneralSecurityException
*/
public static byte[] crypto_box_seal(byte[] clearText, byte[] receiverPubKey) throws GeneralSecurityException {

// create ephemeral keypair for sender
TweetNaclFast.Box.KeyPair ephkeypair = TweetNaclFast.Box.keyPair();
// create nonce
byte[] nonce = crypto_box_seal_nonce(ephkeypair.getPublicKey(), receiverPubKey);
TweetNaclFast.Box box = new TweetNaclFast.Box(receiverPubKey, ephkeypair.getSecretKey());
byte[] ciphertext = box.box(clearText, nonce);
if (ciphertext == null) throw new GeneralSecurityException("could not create box");

byte[] sealedbox = new byte[ciphertext.length + crypto_box_PUBLICKEYBYTES];
byte[] ephpubkey = ephkeypair.getPublicKey();
for (int i = 0; i < crypto_box_PUBLICKEYBYTES; i ++)
sealedbox[i] = ephpubkey[i];

for(int i = 0; i < ciphertext.length; i ++)
sealedbox[i+crypto_box_PUBLICKEYBYTES]=ciphertext[i];

return sealedbox;
}

// libsodium:
// int
// crypto_box_seal_open(unsigned char *m, const unsigned char *c,
// unsigned long long clen,
// const unsigned char *pk, const unsigned char *sk)

/**
* Decrypt a sealed box
*
* @param c ciphertext
* @param pk receiver public key
* @param sk receiver secret key
* @return decrypted message
* @throws GeneralSecurityException
*/
public static byte[] crypto_box_seal_open( byte[]c, byte[] pk, byte[]sk ) throws GeneralSecurityException{
if ( c.length < crypto_box_SEALBYTES) throw new IllegalArgumentException("Ciphertext too short");

byte[] pksender = Arrays.copyOfRange(c, 0, crypto_box_PUBLICKEYBYTES);
byte[] ciphertextwithmac = Arrays.copyOfRange(c, crypto_box_PUBLICKEYBYTES , c.length);
byte[] nonce = crypto_box_seal_nonce(pksender,pk);

TweetNaclFast.Box box = new TweetNaclFast.Box(pksender, sk);
byte[] cleartext = box.open(ciphertextwithmac, nonce);
if (cleartext == null) throw new GeneralSecurityException("could not open box");
return cleartext;
}


/**
* hash the combination of senderpk + mypk into nonce using blake2b hash
* @param senderpk the senders public key
* @param mypk my own public key
* @return the nonce computed using Blake2b generic hash
*/
public static byte[] crypto_box_seal_nonce(byte[] senderpk, byte[] mypk){
// C source ported from libsodium
// crypto_generichash_state st;
//
// crypto_generichash_init(&st, NULL, 0U, crypto_box_NONCEBYTES);
// crypto_generichash_update(&st, pk1, crypto_box_PUBLICKEYBYTES);
// crypto_generichash_update(&st, pk2, crypto_box_PUBLICKEYBYTES);
// crypto_generichash_final(&st, nonce, crypto_box_NONCEBYTES);
//
// return 0;
final Blake2b blake2b = Blake2b.Digest.newInstance( crypto_box_NONCEBYTES );
blake2b.update(senderpk);
blake2b.update(mypk);
byte[] nonce = blake2b.digest();
if (nonce == null || nonce.length!=crypto_box_NONCEBYTES) throw new IllegalArgumentException("Blake2b hashing failed");
return nonce;


}

}

关于java - 如何在纯 Java 中创建或打开与 libsodium 兼容的密封盒,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42456624/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com