javascript - एक पासवर्ड के साथ एक संदेश एन्क्रिप्ट करते समय क्रिप्टो-जेएस द्वारा आंतरिक रूप से प्रदर्शन किए गए एईएस पैरामीटर का उपयोग और चरण क्या हैं?




security encryption (2)

CryptoJS हैशिंग एल्गोरिथ्म और 1 पुनरावृत्ति के रूप में MD5 के साथ कुंजी व्युत्पत्ति ( EvpKDF ) के लिए गैर-मानकीकृत ओपनएसएसएल केडीएफ uses है। IV पासवर्ड से भी लिया गया है जिसका अर्थ है कि केवल वास्तविक सिफरटेक्स्ट, पासवर्ड और नमक को जावा पक्ष में इसे डिक्रिप्ट करने की आवश्यकता है।

दूसरे शब्दों में, CryptoJS के पासवर्ड मोड में कुंजी व्युत्पत्ति के लिए PBKDF2 का उपयोग नहीं किया जाता है। डिफ़ॉल्ट रूप से AES-256 का उपयोग PKBC5 पैडिंग (जो PKCS7 पैडिंग के समान है ) के साथ CBC मोड में किया जाता है। ध्यान रखें कि आपको जेसीई असीमित शक्ति क्षेत्राधिकार नीति फ़ाइलों की आवश्यकता हो सकती है। यह भी देखें कि कुछ निश्चित लंबाई से परे कुंजियों के साथ एन्क्रिप्शन का उपयोग करने की सीमाएं क्यों हैं?

निम्न कोड जावा में केडीएफ को फिर से बनाता है (एईएस-256 के लिए keySize और ivSize 8 क्रमशः 4 हैं और आते हैं)।

public static byte[] evpKDF(byte[] password, int keySize, int ivSize, byte[] salt, int iterations, String hashAlgorithm, byte[] resultKey, byte[] resultIv) throws NoSuchAlgorithmException {
    int targetKeySize = keySize + ivSize;
    byte[] derivedBytes = new byte[targetKeySize * 4];
    int numberOfDerivedWords = 0;
    byte[] block = null;
    MessageDigest hasher = MessageDigest.getInstance(hashAlgorithm);
    while (numberOfDerivedWords < targetKeySize) {
        if (block != null) {
            hasher.update(block);
        }
        hasher.update(password);
        block = hasher.digest(salt);
        hasher.reset();

        // Iterations
        for (int i = 1; i < iterations; i++) {
            block = hasher.digest(block);
            hasher.reset();
        }

        System.arraycopy(block, 0, derivedBytes, numberOfDerivedWords * 4,
                Math.min(block.length, (targetKeySize - numberOfDerivedWords) * 4));

        numberOfDerivedWords += block.length/4;
    }

    System.arraycopy(derivedBytes, 0, resultKey, 0, keySize * 4);
    System.arraycopy(derivedBytes, keySize * 4, resultIv, 0, ivSize * 4);

    return derivedBytes; // key + iv
}

यहाँ संदर्भ के लिए पूरा वर्ग है:

public class RecreateEVPkdfFromCryptoJS {
    public static void main(String[] args) throws UnsupportedEncodingException, GeneralSecurityException {
        String msg = "hello";
        String password = "mypassword";
        String ivHex = "aab7d6aca0cc6ffc18f9f5909753aa5f";
        int keySize = 8; // 8 words = 256-bit
        int ivSize = 4; // 4 words = 128-bit
        String keyHex = "844a86d27d96acf3147aa460f535e20e989d1f8b5d79c0403b4a0f34cebb093b";
        String saltHex = "ca35168ed6b82778";
        String openSslFormattedCipherTextString = "U2FsdGVkX1/KNRaO1rgneK9S3zuYaYZcdXmVKJGqVqk=";
        String cipherTextHex = "af52df3b9869865c7579952891aa56a9";
        String padding = "PKCS5Padding";

        byte[] key = hexStringToByteArray(keyHex);
        byte[] iv = hexStringToByteArray(ivHex);
        byte[] salt = hexStringToByteArray(saltHex);
        byte[] cipherText = hexStringToByteArray(cipherTextHex);

        byte[] javaKey = new byte[keySize * 4];
        byte[] javaIv = new byte[ivSize * 4];
        evpKDF(password.getBytes("UTF-8"), keySize, ivSize, salt, javaKey, javaIv);
        System.out.println(Arrays.equals(key, javaKey) + " " + Arrays.equals(iv, javaIv));

        Cipher aesCipherForEncryption = Cipher.getInstance("AES/CBC/PKCS5Padding"); // Must specify the mode explicitly as most JCE providers default to ECB mode!!

        IvParameterSpec ivSpec = new IvParameterSpec(javaIv);
        aesCipherForEncryption.init(Cipher.DECRYPT_MODE, new SecretKeySpec(javaKey, "AES"), ivSpec);

        byte[] byteMsg = aesCipherForEncryption.doFinal(cipherText);
        System.out.println(Arrays.equals(byteMsg, msg.getBytes("UTF-8")));
    }

    public static byte[] evpKDF(byte[] password, int keySize, int ivSize, byte[] salt, byte[] resultKey, byte[] resultIv) throws NoSuchAlgorithmException {
        return evpKDF(password, keySize, ivSize, salt, 1, "MD5", resultKey, resultIv);
    }

    public static byte[] evpKDF(byte[] password, int keySize, int ivSize, byte[] salt, int iterations, String hashAlgorithm, byte[] resultKey, byte[] resultIv) throws NoSuchAlgorithmException {
        int targetKeySize = keySize + ivSize;
        byte[] derivedBytes = new byte[targetKeySize * 4];
        int numberOfDerivedWords = 0;
        byte[] block = null;
        MessageDigest hasher = MessageDigest.getInstance(hashAlgorithm);
        while (numberOfDerivedWords < targetKeySize) {
            if (block != null) {
                hasher.update(block);
            }
            hasher.update(password);
            block = hasher.digest(salt);
            hasher.reset();

            // Iterations
            for (int i = 1; i < iterations; i++) {
                block = hasher.digest(block);
                hasher.reset();
            }

            System.arraycopy(block, 0, derivedBytes, numberOfDerivedWords * 4,
                    Math.min(block.length, (targetKeySize - numberOfDerivedWords) * 4));

            numberOfDerivedWords += block.length/4;
        }

        System.arraycopy(derivedBytes, 0, resultKey, 0, keySize * 4);
        System.arraycopy(derivedBytes, keySize * 4, resultIv, 0, ivSize * 4);

        return derivedBytes; // key + iv
    }

    /**
     * Copied from http://stackoverflow.com/a/140861
     * */
    public static byte[] hexStringToByteArray(String s) {
        int len = s.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                    + Character.digit(s.charAt(i+1), 16));
        }
        return data;
    }
}

और जावास्क्रिप्ट कोड जो जावा कोड में मूल्यों की पीढ़ी के लिए इस्तेमाल किया गया था:

var msg = "hello";
var password = "mypassword"; // must be present on the server
var encrypted = CryptoJS.AES.encrypt( msg, password );
var ivHex = encrypted.iv.toString();
var ivSize = encrypted.algorithm.ivSize; // same as the blockSize
var keySize = encrypted.algorithm.keySize;
var keyHex = encrypted.key.toString();
var saltHex = encrypted.salt.toString(); // must be sent as well
var openSslFormattedCipherTextString = encrypted.toString(); // not used
var cipherTextHex = encrypted.ciphertext.toString(); // must be sent

पृष्ठभूमि: मैं जिस एप्लिकेशन पर काम कर रहा हूं वह ऑफ़लाइन काम करना है। मुझे जावा सर्वर साइड में एक कुंजी के रूप में पासवर्ड का उपयोग करके कुछ टेक्स्ट डेटा को एन्क्रिप्ट करना चाहिए। एन्क्रिप्ट किए गए डेटा को HTML5 पेज पर भेजा जाता है और क्रिप्टो-जेएस लाइब्रेरी का उपयोग करके क्लाइंट साइड पर सर्वर एन्क्रिप्टेड डेटा को डिक्रिप्ट किया जाना चाहिए।

मेरा मुद्दा: मेरे संदेश को इस तरह से एन्क्रिप्ट करने के लिए कि ग्राहक इसे क्रिप्ट-जेएस (उपयोगकर्ता द्वारा दर्ज पासवर्ड का उपयोग करके) के साथ डिक्रिप्ट कर सकता है, मुझे सटीक चरणों को जानना होगा जो किसी संदेश को एन्क्रिप्ट करते समय क्रिप्टो-जेएस को उम्मीद है।

मुझे क्या जानना चाहिए: मेरे पास निम्न एन्क्रिप्शन कोड है जो क्रिप्टो-जेएस का उपयोग करके क्लाइंट पक्ष पर एक संदेश का एन्क्रिप्शन करता है।

var message = "my message text";
var password = "user password";
var encrypted = CryptoJS.AES.encrypt( message ,password );
console.log(encrypted.toString());

मुझे एक संदेश को एन्क्रिप्ट करते समय CryptoJS द्वारा उपयोग किए जाने वाले एईएस मापदंडों को जानने की जरूरत है ( यकीन नहीं कि वे क्या हैं, लेकिन ऐसा लगता है: कुंजी आकार (256), पैडिंग (pkcs5), मोड (CBC), PBE एल्गोरिथ्म (PBKDF2), नमक ( यादृच्छिक), पुनरावृति गणना (100 )। यह एक बड़ी मदद होगी अगर कोई इसकी पुष्टि कर सकता है ... मैं पिछले कुछ दिनों से इस रहस्य को सुलझाने की कोशिश कर रहा हूं।

एक संदेश को एन्क्रिप्ट करते समय मुझे CryptoJS द्वारा किए गए विभिन्न चरणों को जानना होगा


इस सवाल पर @Artjom B के शानदार जवाब के बाद और अजगर उपयोगकर्ताओं के लिए , मैं पूर्ण जावा कोड में शामिल हो रहा हूं जिसने मुझे एक स्ट्रिंग को डिक्रिप्ट करने में मदद की जो इस तरह से एन्क्रिप्ट की गई थी

var encrypted = CryptoJS.AES.encrypt(message, password).toString();

जावा कोड का यह टुकड़ा तब उपयोगी होता है जब आप केवल पासवर्ड जानते हैं (यानी एन्क्रिप्टेड स्ट्रिंग के साथ नमक नहीं भेजा गया था):

public String decrypt(String encrypted, String password) throws Exception {
    int keySize = 8;
    int ivSize = 4;
    // Start by decoding the encrypted string (Base64)
    // Here I used the Android implementation (other Java implementations might exist)
    byte[] cipherText = Base64.decode(encrypted, Base64.DEFAULT);
    // prefix (first 8 bytes) is not actually useful for decryption, but you should probably check that it is equal to the string "Salted__"
    byte[] prefix = new byte[8];
    System.arraycopy(cipherText, 0, prefix, 0, 8);
    // Check here that prefix is equal to "Salted__"
    // Extract salt (next 8 bytes)
    byte[] salt = new byte[8];
    System.arraycopy(cipherText, 8, salt, 0, 8);
    // Extract the actual cipher text (the rest of the bytes)
    byte[] trueCipherText = new byte[cipherText.length - 16];
    System.arraycopy(cipherText, 16, trueCipherText, 0, cipherText.length - 16);
    byte[] javaKey = new byte[keySize * 4];
    byte[] javaIv = new byte[ivSize * 4];
    evpKDF(password.getBytes("UTF-8"), keySize, ivSize, salt, javaKey, javaIv);
    Cipher aesCipherForEncryption = Cipher.getInstance("AES/CBC/PKCS5Padding");
    IvParameterSpec ivSpec = new IvParameterSpec(javaIv);
    aesCipherForEncryption.init(Cipher.DECRYPT_MODE, new SecretKeySpec(javaKey, "AES"), ivSpec);

    byte[] byteMsg = aesCipherForEncryption.doFinal(trueCipherText);
    return new String(byteMsg, "UTF-8");
}

public  byte[] evpKDF(byte[] password, int keySize, int ivSize, byte[] salt, byte[] resultKey, byte[] resultIv) throws NoSuchAlgorithmException {
    return evpKDF(password, keySize, ivSize, salt, 1, "MD5", resultKey, resultIv);
}

public  byte[] evpKDF(byte[] password, int keySize, int ivSize, byte[] salt, int iterations, String hashAlgorithm, byte[] resultKey, byte[] resultIv) throws NoSuchAlgorithmException {
    int targetKeySize = keySize + ivSize;
    byte[] derivedBytes = new byte[targetKeySize * 4];
    int numberOfDerivedWords = 0;
    byte[] block = null;
    MessageDigest hasher = MessageDigest.getInstance(hashAlgorithm);
    while (numberOfDerivedWords < targetKeySize) {
        if (block != null) {
            hasher.update(block);
        }
        hasher.update(password);
        block = hasher.digest(salt);
        hasher.reset();

        // Iterations
        for (int i = 1; i < iterations; i++) {
            block = hasher.digest(block);
            hasher.reset();
        }

        System.arraycopy(block, 0, derivedBytes, numberOfDerivedWords * 4,
                Math.min(block.length, (targetKeySize - numberOfDerivedWords) * 4));

        numberOfDerivedWords += block.length/4;
    }

    System.arraycopy(derivedBytes, 0, resultKey, 0, keySize * 4);
    System.arraycopy(derivedBytes, keySize * 4, resultIv, 0, ivSize * 4);

    return derivedBytes; // key + iv
}




cryptojs