<commit_before>package com.github.DNAProject.crypto;


import com.github.DNAProject.account.Account;
import com.github.DNAProject.common.ErrorCode;
import com.github.DNAProject.crypto.bip32.HdPrivateKey;
import com.github.DNAProject.crypto.bip32.Bitcoin;
import com.github.DNAProject.sdk.exception.SDKException;

import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.Base64;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import io.github.novacrypto.bip39.MnemonicGenerator;
import io.github.novacrypto.bip39.SeedCalculator;
import io.github.novacrypto.bip39.Words;
import io.github.novacrypto.bip39.wordlists.English;
import org.bouncycastle.crypto.generators.SCrypt;

public class MnemonicCode {

    public static String generateMnemonicCodesStr(){
        return generateMnemonicCodesStr(Words.TWELVE);
    }

    public static String generateMnemonicCodesStr(Words words){
        final StringBuilder sb = new StringBuilder();
        byte[] entropy = new byte[words.byteLength()];
        new SecureRandom().nextBytes(entropy);
        new MnemonicGenerator(English.INSTANCE).createMnemonic(entropy, new MnemonicGenerator.Target() {
            @Override
            public void append(CharSequence string) {
                sb.append(string);
            }
        });
        new SecureRandom().nextBytes(entropy);
        return sb.toString();
    }

    public static byte[] getSeedFromMnemonicCodesStr(String mnemonicCodesStr) throws SDKException {
        if(mnemonicCodesStr == null || mnemonicCodesStr.equals("")){
            throw new SDKException(ErrorCode.ParamErr("mnemonicCodesStr should not be null"));
        }
        String[] mnemonicCodesArray = mnemonicCodesStr.split(" ");
        byte[] seed = new SeedCalculator()
                .withWordsFromWordList(English.INSTANCE)
                .calculateSeed(Arrays.asList(mnemonicCodesArray), "");
        return seed;
    }

    public static byte[] getPrikeyFromMnemonicCodesStrBip44(String mnemonicCodesStr) throws Exception{
        if(mnemonicCodesStr == null || mnemonicCodesStr.equals("")){
            throw new SDKException(ErrorCode.ParamErr("mnemonicCodesStr should not be null"));
        }
        byte[] seed = MnemonicCode.getSeedFromMnemonicCodesStr(mnemonicCodesStr);
        HdPrivateKey key = HdPrivateKey.fromSeed(seed,"Nist256p1 seed".getBytes(StandardCharsets.UTF_8), Bitcoin.MAIN_NET);
        HdPrivateKey child = key.fromPath();
        byte[] p = child.toByteArray();
        byte[] tmp = new byte[32];
        System.arraycopy(p, 46, tmp, 0, 32);
        return tmp;
    }
    public static String encryptMnemonicCodesStr(String mnemonicCodesStr, String password, String address) throws Exception {
        if(mnemonicCodesStr == null || mnemonicCodesStr.equals("") || password==null || password.equals("")||address==null||address.equals("")){
            throw new SDKException(ErrorCode.ParamError);
        }
        int N = 4096;
        int r = 8;
        int p = 8;
        int dkLen = 64;

        byte[] addresshashTmp = Digest.sha256(Digest.sha256(address.getBytes()));
        byte[] salt = Arrays.copyOfRange(addresshashTmp, 0, 4);
        byte[] derivedkey = SCrypt.generate(password.getBytes(StandardCharsets.UTF_8), salt, N, r, p, dkLen);
        password = null;

        byte[] derivedhalf2 = new byte[32];
        byte[] iv = new byte[16];
        System.arraycopy(derivedkey, 0, iv, 0, 16);
        System.arraycopy(derivedkey, 32, derivedhalf2, 0, 32);

        SecretKeySpec skeySpec = new SecretKeySpec(derivedhalf2, "AES");
        Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(iv));
        byte[] encryptedkey = cipher.doFinal(mnemonicCodesStr.getBytes());
        mnemonicCodesStr = null;

        return new String(Base64.getEncoder().encode(encryptedkey));

    }

    public static String decryptMnemonicCodesStr(String encryptedMnemonicCodesStr, String password,String address) throws Exception {
        if (encryptedMnemonicCodesStr == null) {
            throw new SDKException(ErrorCode.ParamError);
        }
        byte[] encryptedkey = Base64.getDecoder().decode(encryptedMnemonicCodesStr);

        int N = 4096;
        int r = 8;
        int p = 8;
        int dkLen = 64;

        byte[] addresshashTmp = Digest.sha256(Digest.sha256(address.getBytes()));
        byte[] salt = Arrays.copyOfRange(addresshashTmp, 0, 4);

        byte[] derivedkey = SCrypt.generate(password.getBytes(StandardCharsets.UTF_8), salt, N, r, p, dkLen);
        password = <PASSWORD>;
        byte[] derivedhalf2 = new byte[32];
        byte[] iv = new byte[16];
        System.arraycopy(derivedkey, 0, iv, 0, 16);
        System.arraycopy(derivedkey, 32, derivedhalf2, 0, 32);

        SecretKeySpec skeySpec = new SecretKeySpec(derivedhalf2, "AES");
        Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
        cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec(iv));
        byte[] rawMns = cipher.doFinal(encryptedkey);
        String mnemonicCodesStr = new String(rawMns);
        byte[] rawkey = MnemonicCode.getPrikeyFromMnemonicCodesStrBip44(mnemonicCodesStr);
        String addressNew = new Account(rawkey, SignatureScheme.SHA256WITHECDSA).getAddressU160().toBase58();
        byte[] addressNewHashTemp = Digest.sha256(Digest.sha256(addressNew.getBytes()));
        byte[] saltNew = Arrays.copyOfRange(addressNewHashTemp, 0, 4);
        if (!Arrays.equals(saltNew, salt)) {
            throw new SDKException(ErrorCode.EncryptedPriKeyError);
        }
        return mnemonicCodesStr;
    }


    public static char[] getChars(byte[] bytes) {
        char[] chars = new char[bytes.length];
        for (int i = 0; i < bytes.length; i++) {
            chars[i] = (char) bytes[i];
        }
        return chars;
    }
}
<commit_msg>fix getPrikeyFromMnemonicCodesStrBip44 bug<commit_after>package com.github.DNAProject.crypto;


import com.github.DNAProject.account.Account;
import com.github.DNAProject.common.ErrorCode;
import com.github.DNAProject.crypto.bip32.HdPrivateKey;
import com.github.DNAProject.crypto.bip32.Bitcoin;
import com.github.DNAProject.sdk.exception.SDKException;

import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.Base64;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import io.github.novacrypto.bip39.MnemonicGenerator;
import io.github.novacrypto.bip39.SeedCalculator;
import io.github.novacrypto.bip39.Words;
import io.github.novacrypto.bip39.wordlists.English;
import org.bouncycastle.crypto.generators.SCrypt;

public class MnemonicCode {

    public static String generateMnemonicCodesStr(){
        return generateMnemonicCodesStr(Words.TWELVE);
    }

    public static String generateMnemonicCodesStr(Words words){
        final StringBuilder sb = new StringBuilder();
        byte[] entropy = new byte[words.byteLength()];
        new SecureRandom().nextBytes(entropy);
        new MnemonicGenerator(English.INSTANCE).createMnemonic(entropy, new MnemonicGenerator.Target() {
            @Override
            public void append(CharSequence string) {
                sb.append(string);
            }
        });
        new SecureRandom().nextBytes(entropy);
        return sb.toString();
    }

    public static byte[] getSeedFromMnemonicCodesStr(String mnemonicCodesStr) throws SDKException {
        if(mnemonicCodesStr == null || mnemonicCodesStr.equals("")){
            throw new SDKException(ErrorCode.ParamErr("mnemonicCodesStr should not be null"));
        }
        String[] mnemonicCodesArray = mnemonicCodesStr.split(" ");
        byte[] seed = new SeedCalculator()
                .withWordsFromWordList(English.INSTANCE)
                .calculateSeed(Arrays.asList(mnemonicCodesArray), "");
        return seed;
    }

    public static byte[] getPrikeyFromMnemonicCodesStrBip44(String mnemonicCodesStr) throws Exception{
        if(mnemonicCodesStr == null || mnemonicCodesStr.equals("")){
            throw new SDKException(ErrorCode.ParamErr("mnemonicCodesStr should not be null"));
        }
        byte[] seed = MnemonicCode.getSeedFromMnemonicCodesStr(mnemonicCodesStr);
        HdPrivateKey key = HdPrivateKey.fromSeed(seed,"Nist256p1 seed".getBytes(StandardCharsets.UTF_8), Bitcoin.MAIN_NET);
        HdPrivateKey child = key.fromPath().cKDpriv(0).cKDpriv(0);
        byte[] p = child.toByteArray();
        byte[] tmp = new byte[32];
        System.arraycopy(p, 46, tmp, 0, 32);
        return tmp;
    }
    public static String encryptMnemonicCodesStr(String mnemonicCodesStr, String password, String address) throws Exception {
        if(mnemonicCodesStr == null || mnemonicCodesStr.equals("") || password==null || password.equals("")||address==null||address.equals("")){
            throw new SDKException(ErrorCode.ParamError);
        }
        int N = 4096;
        int r = 8;
        int p = 8;
        int dkLen = 64;

        byte[] addresshashTmp = Digest.sha256(Digest.sha256(address.getBytes()));
        byte[] salt = Arrays.copyOfRange(addresshashTmp, 0, 4);
        byte[] derivedkey = SCrypt.generate(password.getBytes(StandardCharsets.UTF_8), salt, N, r, p, dkLen);
        password = null;

        byte[] derivedhalf2 = new byte[32];
        byte[] iv = new byte[16];
        System.arraycopy(derivedkey, 0, iv, 0, 16);
        System.arraycopy(derivedkey, 32, derivedhalf2, 0, 32);

        SecretKeySpec skeySpec = new SecretKeySpec(derivedhalf2, "AES");
        Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(iv));
        byte[] encryptedkey = cipher.doFinal(mnemonicCodesStr.getBytes());
        mnemonicCodesStr = null;

        return new String(Base64.getEncoder().encode(encryptedkey));

    }

    public static String decryptMnemonicCodesStr(String encryptedMnemonicCodesStr, String password,String address) throws Exception {
        if (encryptedMnemonicCodesStr == null) {
            throw new SDKException(ErrorCode.ParamError);
        }
        byte[] encryptedkey = Base64.getDecoder().decode(encryptedMnemonicCodesStr);

        int N = 4096;
        int r = 8;
        int p = 8;
        int dkLen = 64;

        byte[] addresshashTmp = Digest.sha256(Digest.sha256(address.getBytes()));
        byte[] salt = Arrays.copyOfRange(addresshashTmp, 0, 4);

        byte[] derivedkey = SCrypt.generate(password.getBytes(StandardCharsets.UTF_8), salt, N, r, p, dkLen);
        password = <PASSWORD>;
        byte[] derivedhalf2 = new byte[32];
        byte[] iv = new byte[16];
        System.arraycopy(derivedkey, 0, iv, 0, 16);
        System.arraycopy(derivedkey, 32, derivedhalf2, 0, 32);

        SecretKeySpec skeySpec = new SecretKeySpec(derivedhalf2, "AES");
        Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
        cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec(iv));
        byte[] rawMns = cipher.doFinal(encryptedkey);
        String mnemonicCodesStr = new String(rawMns);
        byte[] rawkey = MnemonicCode.getPrikeyFromMnemonicCodesStrBip44(mnemonicCodesStr);
        String addressNew = new Account(rawkey, SignatureScheme.SHA256WITHECDSA).getAddressU160().toBase58();
        byte[] addressNewHashTemp = Digest.sha256(Digest.sha256(addressNew.getBytes()));
        byte[] saltNew = Arrays.copyOfRange(addressNewHashTemp, 0, 4);
        if (!Arrays.equals(saltNew, salt)) {
            throw new SDKException(ErrorCode.EncryptedPriKeyError);
        }
        return mnemonicCodesStr;
    }


    public static char[] getChars(byte[] bytes) {
        char[] chars = new char[bytes.length];
        for (int i = 0; i < bytes.length; i++) {
            chars[i] = (char) bytes[i];
        }
        return chars;
    }
}

{'fraction_non_alphanumeric': 0.11311352877667968, 'fraction_numerical': 0.019765800182709077, 'mean_word_length': 3.2747603833865813, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 5, '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': '3400711', 'n_tokens_mistral': 3945, 'n_tokens_neox': 3671, 'n_words': 728}