1

nacl.box我们的项目使用带有临时密钥的非对称加密:

    encrypt(pubKey, msg) {
        if (typeof msg !== 'string') {
            msg = JSON.stringify(msg)
        }
        let ephemKeys = nacl.box.keyPair()
        let msgArr = nacl.util.decodeUTF8(msg)
        let nonce = nacl.randomBytes(nacl.box.nonceLength)
        p(`naclRsa.pubKey=${this.pubKey}`)
        let encrypted = nacl.box(
            msgArr,
            nonce,
            nacl.util.decodeBase64(pubKey),
            ephemKeys.secretKey
        )
        let nonce64 = nacl.util.encodeBase64(nonce)
        let pubKey64 = nacl.util.encodeBase64(ephemKeys.publicKey)
        let encrypted64 = nacl.util.encodeBase64(encrypted)
        return {nonce: nonce64, ephemPubKey: pubKey64, encrypted: encrypted64}
    }

我们目前有node.js可以解密这些消息的应用程序。我们希望选择jvm为某些功能使用语言。似乎没有老牌玩家的丰富性,tweet-nacljvm似乎

及其推荐的实施

° tweetnacl-fast https://github.com/InstantWebP2P/tweetnacl-java/blob/master/src/main/java/com/iwebpp/crypto/TweetNaclFast.java

是一个受欢迎的。

目前尚不清楚asymmetric该库中使用临时密钥进行加密的类似物是什么。是否支持?请注意javakotlin如果tweetnacl-java.

4

2 回答 2

1

tweetnacl-javatweetnacl-js的一个端口。因此,可以预期两者都提供相同的功能。至少对于发布的方法是这样的,它可以在 Java 端使用TweetNaclFast实现,如下所示:

import java.nio.charset.StandardCharsets;
import java.util.Base64;

import com.iwebpp.crypto.TweetNaclFast;
import com.iwebpp.crypto.TweetNaclFast.Box;
import com.iwebpp.crypto.TweetNaclFast.Box.KeyPair;

...

private static EncryptedData encrypt(byte[] pubKey, String msg) {
    KeyPair ephemKeys = Box.keyPair();
    byte[] msgArr = msg.getBytes(StandardCharsets.UTF_8);
    byte[] nonce = TweetNaclFast.randombytes(Box.nonceLength);
    
    Box box = new Box(pubKey, ephemKeys.getSecretKey());
    byte[] encrypted = box.box(msgArr, nonce);
    
    String nonce64 = Base64.getEncoder().encodeToString(nonce);
    String ephemPubKey64 = Base64.getEncoder().encodeToString(ephemKeys.getPublicKey());
    String encrypted64 = Base64.getEncoder().encodeToString(encrypted);
    return new EncryptedData(nonce64, ephemPubKey64, encrypted64);
}

...

class EncryptedData {
    public EncryptedData(String nonce, String ephemPubKey, String encrypted) {
        this.nonce = nonce;
        this.ephemPubKey = ephemPubKey;
        this.encrypted = encrypted;
    }
    public String nonce;
    public String ephemPubKey;
    public String encrypted;
}

为了证明双方是兼容的,下面将一段明文在 Java 端加密,在 JavaScript 端解密:

  • 首先,在 JavaScript 端需要一个密钥对,其公钥 ( publicKeyJS) 被传递到 Java 端。JavaScript 端的密钥对可以生成如下:

    let keysJS = nacl.box.keyPair();
    let secretKeyJS = keysJS.secretKey;
    let publicKeyJS = keysJS.publicKey;
    console.log("Secret key: " + nacl.util.encodeBase64(secretKeyJS));
    console.log("Public key: " + nacl.util.encodeBase64(publicKeyJS));
    

    具有以下示例输出:

    Secret key: YTxAFmYGm4yV2OP94E4pcD6LSsN4gcSBBAlU105l7hw= 
    Public key: BDXNKDHeq0vILm8oawAGAQtdIsgwethzBTBqmsWI+R8=
    
  • 然后,Java 端的加密使用encrypt上面发布的方法(和publicKeyJS):

    byte[] publicKeyJS = Base64.getDecoder().decode("BDXNKDHeq0vILm8oawAGAQtdIsgwethzBTBqmsWI+R8=");
    EncryptedData encryptedFromJava = encrypt(publicKeyJS, "I've got a feeling we're not in Kansas anymore...");
    System.out.println("Nonce: " + encryptedFromJava.nonce);
    System.out.println("Ephemeral public key: " + encryptedFromJava.ephemPubKey);
    System.out.println("Ciphertext: " + encryptedFromJava.encrypted);
    

    具有以下示例输出:

    Nonce: FcdzXfYwSbI0nq2WXsLe9aAh94vXSoWd
    Ephemeral public key: Mde+9metwF1jIEij5rlZDHjAStR/pd4BN9p5JbZleSg=
    Ciphertext: hHo7caCxTU+hghcFZFv+djAkSlWKnC12xj82V2R/Iz9GdOMoTzjoCDcz9m/KbRN6i5dkYi3+Gf0YTtKlZQWFooo=
    
  • JS端解密给出原始明文(使用secretKeyJS):

    let nonce = "FcdzXfYwSbI0nq2WXsLe9aAh94vXSoWd";
    let ephemPubKey = "Mde+9metwF1jIEij5rlZDHjAStR/pd4BN9p5JbZleSg=";
    let encrypted = "hHo7caCxTU+hghcFZFv+djAkSlWKnC12xj82V2R/Iz9GdOMoTzjoCDcz9m/KbRN6i5dkYi3+Gf0YTtKlZQWFooo=";
    let secretKeyJS = nacl.util.decodeBase64("YTxAFmYGm4yV2OP94E4pcD6LSsN4gcSBBAlU105l7hw=");
    let decryptedFromJS = decrypt(secretKeyJS, {nonce: nonce, ephemPubKey: ephemPubKey, encrypted: encrypted});
    console.log(nacl.util.encodeUTF8(decryptedFromJS)); // I've got a feeling we're not in Kansas anymore...
      
    function decrypt(secretKey, ciphertext){
        let decrypted = nacl.box.open(
            nacl.util.decodeBase64(ciphertext.encrypted),
            nacl.util.decodeBase64(ciphertext.nonce),
            nacl.util.decodeBase64(ciphertext.ephemPubKey),
            secretKey
        );
        return decrypted;
    }
    <script src="https://cdn.jsdelivr.net/npm/tweetnacl-util@0.15.1/nacl-util.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/tweetnacl@1.0.3/nacl.min.js"></script>
    
       

于 2020-09-04T15:52:23.703 回答
0

我的 tweetnacl-java 完整代码(感谢@topaco)

我生成了两个随机密钥对并将它们的密钥保存在 application.properties 文件中,这样,我将始终拥有相同的 pub&sec 以及随机数。

KeyPair baseKeyPair= Box.keyPair(); 字符串 baseKeyPairSecretKey = Base64.getEncoder().encodeToString(baseKeyPair.getSecretKey());

KeyPair ephemeralKeyPair= Box.keyPair(); 字符串 ephemeralKeyPairSecretKey = Base64.getEncoder().encodeToString(ephemeralKeyPair.getSecretKey());

byte[] nonce = TweetNaclFast.randombytes(Box.nonceLength); String nonce64 = Base64.getEncoder().encodeToString(nonce);

 private final AppConfig config; //you can autowire the config class 

 private TweetNaclFast.Box.KeyPair getBaseKeyPair() {
        byte[] secretKey = Base64.getDecoder().decode(config.getTweetNACLConfig().getBaseSecretKey());
        return TweetNaclFast.Box.keyPair_fromSecretKey(mySecretKey);
    }


    private TweetNaclFast.Box.KeyPair getEphemeralKeyPair() {
        byte[] secretKey = Base64.getDecoder().decode(config.getTweetNACLConfig().getEphemeralSecretKey());
        return TweetNaclFast.Box.keyPair_fromSecretKey(mySecretKey);
    }


    private byte[] getNonce() {
        return Base64.getDecoder().decode(config.getTweetNACLConfig().getNonce().getBytes(StandardCharsets.UTF_8));
    }

    public String encrypt(String msg) {
        TweetNaclFast.Box.KeyPair baseKeyPair = getBaseKeyPair();
        TweetNaclFast.Box.KeyPair ephemeralKeyPair = getEphemeralKeyPair();
        byte[] msgArr = msg.getBytes(StandardCharsets.UTF_8);
        byte[] nonce = getNonce();
        TweetNaclFast.Box box = new TweetNaclFast.Box(baseKeyPair.getPublicKey(), ephemeralKeyPair.getSecretKey());
        byte[] encryptedData = box.box(msgArr, nonce);
        return Base64.getEncoder().encodeToString(encryptData);
    }


    public String decrypt(String encryptedData) {
        TweetNaclFast.Box.KeyPair baseKeyPair = getBaseKeyPair();
        TweetNaclFast.Box.KeyPair ephemeralKeyPair = getEphemeralKeyPair();
        byte[] nonce = getNonce();
        TweetNaclFast.Box box = new TweetNaclFast.Box(ephemeralKeyPair.getPublicKey(), baseKeyPair.getSecretKey());
        byte[] boxToOpen = Base64.getDecoder().decode(encryptedData);
        byte[] decryptedData = box.open(boxToOpen, nonce);
        return new String(decryptedData, StandardCharsets.UTF_8);
    }

> Please, note these two lines
> TweetNaclFast.Box box = new TweetNaclFast.Box(baseKeyPair.getPublicKey(), ephemeralKeyPair.getSecretKey());
> TweetNaclFast.Box box = new TweetNaclFast.Box(ephemeralKeyPair.getPublicKey(), baseKeyPair.getSecretKey());

return encryptAndDecryptData.encrypt("Friday"); // JHo/tk/Jpp2rpxpzIIgBhVhK/CBZLg==
return encryptAndDecryptData.decrypt("JHo/tk/Jpp2rpxpzIIgBhVhK/CBZLg==") //Friday
于 2021-08-23T16:34:57.900 回答