<commit_before>package peergos.crypto;

import peergos.util.*;

import java.security.*;
import java.util.Arrays;
import java.util.Random;

/* Ported from the original C by <NAME> and <NAME>
 * crypto_hash() is ported from TweetNaCl.js
 * Released under GPL 2
 */
public class TweetNaCl {

    public static final int crypto_auth_hmacsha512256_tweet_BYTES = 32;
    public static final int crypto_auth_hmacsha512256_tweet_KEYBYTES = 32;
    public static final int BOX_PUBLIC_KEY_BYTES = 32;
    public static final int BOX_SECRET_KEY_BYTES = 32;
    public static final int BOX_SHARED_KEY_BYTES = 32;
    public static final int BOX_NONCE_BYTES = 24;
    public static final int BOX_OVERHEAD_BYTES = 16;
    public static final int SIGNATURE_SIZE_BYTES = 64;
    public static final int SIGN_PUBLIC_KEY_BYTES = 32;
    public static final int SIGN_SECRET_KEY_BYTES = 64;
    public static final int SIGN_KEYPAIR_SEED_BYTES = 32;
    public static final int SECRETBOX_KEY_BYTES = 32;
    public static final int SECRETBOX_NONCE_BYTES = 24;
    public static final int SECRETBOX_OVERHEAD_BYTES = 16;
    public static final int HASH_SIZE_BYTES = 64; // SHA-512
    private static final int SECRETBOX_INTERNAL_OVERHEAD_BYTES = 32;

    public static class InvalidSignatureException extends RuntimeException {}
    public static class InvalidCipherTextException extends IllegalStateException {
        InvalidCipherTextException() {}
        InvalidCipherTextException(String msg) {
            super(msg);
        }
    }

    public static void crypto_sign_keypair(byte[] pk, byte[] sk, boolean isSeeded)
    {
        byte[] d = new byte[64];
        long[][] /*gf*/ p = new long[4][GF_LEN];
        int i;

        if (!isSeeded)
            randombytes(sk, 32);
        crypto_hash(d, sk, 32);
        d[0] &= 248;
        d[31] &= 127;
        d[31] |= 64;

        scalarbase(p,d, 0);
        pack(pk,p);

        for (i=0;i < 32;++i)sk[32 + i] = pk[i];
    }

    public static int crypto_box_keypair(byte[] y,byte[] x, boolean isSeeded)
    {
        if (!isSeeded)
            randombytes(x,32);
        return crypto_scalarmult_base(y,x);
    }

    public static int crypto_scalarmult_base(byte[] q,byte[] n)
    {
        return crypto_scalarmult(q, n, _9);
    }

    public static byte[] crypto_sign(byte[] message, byte[] secretSigningKey) {
        byte[] signedMessage = new byte[message.length + TweetNaCl.SIGNATURE_SIZE_BYTES];
        TweetNaCl.crypto_sign(signedMessage, message, message.length, secretSigningKey);
        return signedMessage;
    }

    public static byte[] crypto_sign_open(byte[] signed, byte[] publicSigningKey) {
        byte[] message = new byte[signed.length];
        int res = TweetNaCl.crypto_sign_open(message, signed, signed.length, publicSigningKey);
        if (res != 0)
            throw new InvalidSignatureException();
        return Arrays.copyOfRange(message, 64, message.length);
    }

    public static byte[] crypto_box(byte[] message, byte[] nonce, byte[] theirPublicBoxingKey, byte[] ourSecretBoxingKey) {
        if (nonce.length != BOX_NONCE_BYTES)
            throw new IllegalStateException("Illegal nonce length: "+nonce.length);
        byte[] cipherText = new byte[SECRETBOX_INTERNAL_OVERHEAD_BYTES + message.length];
        byte[] paddedMessage = new byte[SECRETBOX_INTERNAL_OVERHEAD_BYTES + message.length];
        System.arraycopy(message, 0, paddedMessage, SECRETBOX_INTERNAL_OVERHEAD_BYTES, message.length);
        TweetNaCl.crypto_box(cipherText, paddedMessage, paddedMessage.length, nonce, theirPublicBoxingKey, ourSecretBoxingKey);
        return Arrays.copyOfRange(cipherText, 16, cipherText.length);
    }

    public static byte[] crypto_box_open(byte[] cipher, byte[] nonce, byte[] theirPublicBoxingKey, byte[] secretBoxingKey) {
        byte[] paddedCipher = new byte[cipher.length + 16];
        System.arraycopy(cipher, 0, paddedCipher, 16, cipher.length);
        byte[] rawText = new byte[paddedCipher.length];
        int res = TweetNaCl.crypto_box_open(rawText, paddedCipher, paddedCipher.length, nonce, theirPublicBoxingKey, secretBoxingKey);
        if (res != 0)
            throw new InvalidCipherTextException();
        return Arrays.copyOfRange(rawText, 32, rawText.length);
    }

    public static byte[] secretbox(byte[] mesage, byte[] nonce, byte[] key) {
        byte[] m = new byte[SECRETBOX_INTERNAL_OVERHEAD_BYTES + mesage.length];
        byte[] c = new byte[m.length];
        System.arraycopy(mesage, 0, m, SECRETBOX_INTERNAL_OVERHEAD_BYTES, mesage.length);
        crypto_secretbox(c, m, m.length, nonce, key);
        return Arrays.copyOfRange(c, SECRETBOX_OVERHEAD_BYTES, c.length);
    }

    public static byte[] secretbox_open(byte[] cipher, byte[] nonce, byte[] key) {
        byte[] c = new byte[SECRETBOX_OVERHEAD_BYTES + cipher.length];
        byte[] m = new byte[c.length];
        System.arraycopy(cipher, 0, c, SECRETBOX_OVERHEAD_BYTES, cipher.length);
        boolean isValid = c.length >=32 && crypto_secretbox_open(m, c, c.length, nonce, key) != 0;

        String exMsg = "Invalid encryption! ["+ cipher.length + "] = " +
                ArrayOps.bytesToHex(Arrays.copyOfRange(cipher, 0, Math.min(cipher.length, 64))) + " ... " +
                ArrayOps.bytesToHex(Arrays.copyOfRange(cipher, Math.max(0, cipher.length - 64), cipher.length));

        InvalidCipherTextException ex =  new InvalidCipherTextException(exMsg);

        if (! isValid)
            throw ex;

        return Arrays.copyOfRange(m, SECRETBOX_INTERNAL_OVERHEAD_BYTES, m.length);
    }

    private static byte[] _0 = new byte[16], _9 = new byte[32];
    static {
        _9[0] = 9;<commit_msg>Updated TweetNacl secret_box_open<commit_after>package peergos.crypto;

import peergos.util.*;

import java.security.*;
import java.util.Arrays;
import java.util.Random;

/* Ported from the original C by <NAME> and <NAME>
 * crypto_hash() is ported from TweetNaCl.js
 * Released under GPL 2
 */
public class TweetNaCl {

    public static final int crypto_auth_hmacsha512256_tweet_BYTES = 32;
    public static final int crypto_auth_hmacsha512256_tweet_KEYBYTES = 32;
    public static final int BOX_PUBLIC_KEY_BYTES = 32;
    public static final int BOX_SECRET_KEY_BYTES = 32;
    public static final int BOX_SHARED_KEY_BYTES = 32;
    public static final int BOX_NONCE_BYTES = 24;
    public static final int BOX_OVERHEAD_BYTES = 16;
    public static final int SIGNATURE_SIZE_BYTES = 64;
    public static final int SIGN_PUBLIC_KEY_BYTES = 32;
    public static final int SIGN_SECRET_KEY_BYTES = 64;
    public static final int SIGN_KEYPAIR_SEED_BYTES = 32;
    public static final int SECRETBOX_KEY_BYTES = 32;
    public static final int SECRETBOX_NONCE_BYTES = 24;
    public static final int SECRETBOX_OVERHEAD_BYTES = 16;
    public static final int HASH_SIZE_BYTES = 64; // SHA-512
    private static final int SECRETBOX_INTERNAL_OVERHEAD_BYTES = 32;

    public static class InvalidSignatureException extends RuntimeException {}
    public static class InvalidCipherTextException extends IllegalStateException {
        InvalidCipherTextException() {}
        InvalidCipherTextException(String msg) {
            super(msg);
        }
    }

    public static void crypto_sign_keypair(byte[] pk, byte[] sk, boolean isSeeded)
    {
        byte[] d = new byte[64];
        long[][] /*gf*/ p = new long[4][GF_LEN];
        int i;

        if (!isSeeded)
            randombytes(sk, 32);
        crypto_hash(d, sk, 32);
        d[0] &= 248;
        d[31] &= 127;
        d[31] |= 64;

        scalarbase(p,d, 0);
        pack(pk,p);

        for (i=0;i < 32;++i)sk[32 + i] = pk[i];
    }

    public static int crypto_box_keypair(byte[] y,byte[] x, boolean isSeeded)
    {
        if (!isSeeded)
            randombytes(x,32);
        return crypto_scalarmult_base(y,x);
    }

    public static int crypto_scalarmult_base(byte[] q,byte[] n)
    {
        return crypto_scalarmult(q, n, _9);
    }

    public static byte[] crypto_sign(byte[] message, byte[] secretSigningKey) {
        byte[] signedMessage = new byte[message.length + TweetNaCl.SIGNATURE_SIZE_BYTES];
        TweetNaCl.crypto_sign(signedMessage, message, message.length, secretSigningKey);
        return signedMessage;
    }

    public static byte[] crypto_sign_open(byte[] signed, byte[] publicSigningKey) {
        byte[] message = new byte[signed.length];
        int res = TweetNaCl.crypto_sign_open(message, signed, signed.length, publicSigningKey);
        if (res != 0)
            throw new InvalidSignatureException();
        return Arrays.copyOfRange(message, 64, message.length);
    }

    public static byte[] crypto_box(byte[] message, byte[] nonce, byte[] theirPublicBoxingKey, byte[] ourSecretBoxingKey) {
        if (nonce.length != BOX_NONCE_BYTES)
            throw new IllegalStateException("Illegal nonce length: "+nonce.length);
        byte[] cipherText = new byte[SECRETBOX_INTERNAL_OVERHEAD_BYTES + message.length];
        byte[] paddedMessage = new byte[SECRETBOX_INTERNAL_OVERHEAD_BYTES + message.length];
        System.arraycopy(message, 0, paddedMessage, SECRETBOX_INTERNAL_OVERHEAD_BYTES, message.length);
        TweetNaCl.crypto_box(cipherText, paddedMessage, paddedMessage.length, nonce, theirPublicBoxingKey, ourSecretBoxingKey);
        return Arrays.copyOfRange(cipherText, 16, cipherText.length);
    }

    public static byte[] crypto_box_open(byte[] cipher, byte[] nonce, byte[] theirPublicBoxingKey, byte[] secretBoxingKey) {
        byte[] paddedCipher = new byte[cipher.length + 16];
        System.arraycopy(cipher, 0, paddedCipher, 16, cipher.length);
        byte[] rawText = new byte[paddedCipher.length];
        int res = TweetNaCl.crypto_box_open(rawText, paddedCipher, paddedCipher.length, nonce, theirPublicBoxingKey, secretBoxingKey);
        if (res != 0)
            throw new InvalidCipherTextException();
        return Arrays.copyOfRange(rawText, 32, rawText.length);
    }

    public static byte[] secretbox(byte[] mesage, byte[] nonce, byte[] key) {
        byte[] m = new byte[SECRETBOX_INTERNAL_OVERHEAD_BYTES + mesage.length];
        byte[] c = new byte[m.length];
        System.arraycopy(mesage, 0, m, SECRETBOX_INTERNAL_OVERHEAD_BYTES, mesage.length);
        crypto_secretbox(c, m, m.length, nonce, key);
        return Arrays.copyOfRange(c, SECRETBOX_OVERHEAD_BYTES, c.length);
    }

    public static byte[] secretbox_open(byte[] cipher, byte[] nonce, byte[] key) {
        byte[] c = new byte[SECRETBOX_OVERHEAD_BYTES + cipher.length];
        byte[] m = new byte[c.length];
        System.arraycopy(cipher, 0, c, SECRETBOX_OVERHEAD_BYTES, cipher.length);
        boolean validCipher = c.length >= 32;
        boolean success = crypto_secretbox_open(m, c, c.length, nonce, key) == 0;
        boolean isValid = validCipher && success;

        String exMsg = "Invalid encryption! ["+ cipher.length + "] = " +
                ArrayOps.bytesToHex(Arrays.copyOfRange(cipher, 0, Math.min(cipher.length, 64))) + " ... " +
                ArrayOps.bytesToHex(Arrays.copyOfRange(cipher, Math.max(0, cipher.length - 64), cipher.length));

        InvalidCipherTextException ex =  new InvalidCipherTextException(exMsg);

        if (! isValid)
            throw ex;

        return Arrays.copyOfRange(m, SECRETBOX_INTERNAL_OVERHEAD_BYTES, m.length);
    }

    private static byte[] _0 = new byte[16], _9 = new byte[32];
    static {
        _9[0] = 9;
{'fraction_non_alphanumeric': 0.10375141439637915, 'fraction_numerical': 0.019322830533553836, 'mean_word_length': 3.2969334330590874, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '649256', 'n_tokens_mistral': 3935, 'n_tokens_neox': 3640, 'n_words': 895}