使用密码加密消息时,crypto-js 使用的 AES 参数和内部执行的步骤是什么?

2024-03-08

背景:我正在开发的应用程序应该可以离线工作。我应该在java服务器端使用密码作为密钥来加密一些文本数据。加密的数据被传递到 HTML5 页面,并在客户端使用 crypto-js 库对服务器加密的数据进行解密。

我的问题:为了以客户端可以使用 crypt-js (使用用户输入的密码)解密我的消息的方式加密我的消息,我需要知道 crypto-js 在加密消息时期望的确切步骤。

我需要知道什么:我有以下加密代码,它使用 crypto-js 在客户端对消息进行加密。

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

我需要知道 CryptoJS 在加密消息时使用的 AES 参数(不确定它们是什么,但听起来像:密钥大小(256),填充(pkcs5),模式(CBC),PBE算法(PBKDF2),盐(随机),迭代计数(100))。如果有人能证实这一点,那将是一个很大的帮助……过去几天我一直在试图解开这个谜团?

我需要知道 AES 加密消息时 CryptoJS 执行的不同步骤


加密JSuses https://github.com/CryptoStore/crypto-js/tree/3.1.2/src/cipher-core.js用于密钥派生的非标准化 OpenSSL KDF (EvpKDF https://github.com/CryptoStore/crypto-js/tree/3.1.2/src/evpkdf.js) with MD5作为哈希算法和1迭代。 IV 也是从密码派生的,这意味着在 Java 端解密只需要实际的密文、密码和盐。

换句话说,在CryptoJS的密码模式下,PBKDF2不用于密钥推导。默认情况下,AES-256 用于带有 PKCS5 填充的 CBC 模式(这是与 PKCS7 填充相同 https://crypto.stackexchange.com/questions/9043/what-is-the-difference-between-pkcs5-padding-and-pkcs7-padding)。请记住,您可能需要JCE 无限强度管辖权政策文件 http://www.oracle.com/technetwork/java/javase/downloads/index.html。也可以看看为什么使用超过一定长度的密钥进行加密会受到限制? https://crypto.stackexchange.com/questions/20524/why-there-are-limitations-on-using-encryption-with-keys-beyond-certain-length

以下代码在 Java 中重新创建 KDF (keySize and ivSize对于 AES-256,分别为 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;
    }
}

以及用于生成 Java 代码中的值的 JavaScript 代码:

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
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用密码加密消息时,crypto-js 使用的 AES 参数和内部执行的步骤是什么? 的相关文章

  • Firebase,只得到新的孩子[重复]

    这个问题在这里已经有答案了 var firebase new Firebase firebaseRef on child added function snapshot 这将接收所有元素 有没有办法在创建新的 Firebase 引用时不接收
  • 使用 Angular 指令禁用文本选择

    我正在学习 JavaScript 和 AngularJS 我想使用 Angular Directive 禁用文本选择 我有该函数的 JavaScript 代码 function clearSelection if document sele
  • 使用 Node.js 构建网站的最佳实践

    这个问题的答案是社区努力 help privileges edit community wiki 编辑现有答案以改进这篇文章 目前不接受新的答案或互动 我想知道如何使用 Node js 从头开始 开发一个网站 我明白我怎么能possibly
  • Python PAM 模块的安全问题?

    我有兴趣编写一个 PAM 模块 该模块将利用流行的 Unix 登录身份验证机制 我过去的大部分编程经验都是使用 Python 进行的 并且我正在交互的系统已经有一个 Python API 我用谷歌搜索发现pam python http pa
  • 通过 JavaScript 获取表单名称

    我有一个简单的问题 但我在网上找不到好的解决方案 我有这个 HTML 代码
  • 想要动态处理与分页相关的页码显示:ReactJS

    我有一些分页逻辑工作得很好 唯一的问题是我只能让它显示并固定数量的页面可供选择 现在我已经把它放到了 5 页 但我希望它能够根据总记录动态更改 假设我有 100 条记录 每页限制为 10 条 将有 10 页 现在我只能让它以这种方式显示 第
  • Java AES 128 加密方式与 openssl 不同

    我们遇到了一种奇怪的情况 即我们在 Java 中使用的加密方法会向 openssl 生成不同的输出 尽管它们在配置上看起来相同 使用相同的键和 IV 文本 敏捷的棕色狐狸跳过了懒狗 加密为 Base64 字符串 openssl A8cMRI
  • javascript 选择自定义光标 (svg)

    我正在动态地将光标更改为悬停时的本地 svg element on mouseover function this css cursor url svgs pointer svg 9 30 auto 工作正常 但我想选择该 svg 来操纵其
  • 如何通过单击链接来更改 div 的内容?

    这是我的网页的 修改后的 jsfiddle 它还有很多 而且定位是正确的 与此相反 http jsfiddle net ry0tec3p 1 http jsfiddle net ry0tec3p 1 a href class btn1 st
  • 计算三次贝塞尔曲线的弧长、曲线长度。为什么不工作?

    我正在用这个算法计算弧长 三次贝塞尔曲线的长度 function getArcLength path var STEPS 1000 gt precision var t 1 STEPS var aX 0 var aY 0 var bX 0
  • mongodb 聚合 - 累积字段的不同组值

    如果我有Player表格文件 name String score Int 我有Group文档 其中组代表玩家列表 groupName String players ObjectID 玩家可以属于多个组 我想做一个聚合Player文档 按以下
  • LeafleteachLayer函数不会迭代所有Layer

    使用 GeoJSON 数据数组创建一些标记 getJSON GetLocationsServlet function data L geoJSON data onEachFeature onEachFeature addTo mymap G
  • 聆听 Angular 2 中的元素可见性

    我正在为我的网络应用程序使用 Bootstrap 和 Angular 2 v4 我想监听指令中的元素以了解可见性变化 我的元素有一个可以隐藏其子元素的父元素hidden sm up我需要在每次隐藏或显示时触发一个函数 div hidden
  • 使用javascript动态更新css内容

    需要将 css 更新为动态值 我不确定最好的方法是什么 div style zoom 1 div 缩放级别将根据窗口大小调整触发 应用程序将相应缩放 我将此应用程序加载到 cordova 中并让它在 iPAD 中运行 然后我意识到需要使用
  • 使用 Jade 评估自定义 javascript 方法 (CircularJSON)

    我想通过 Jade 将一个对象解析为客户端 JavaScript 通常这会起作用 script var object JSON parse JSON stringify object but my object is circular ht
  • 主页(网格)上的缩略图现在显得模糊。如何纠正?

    我不知道这看起来是否愚蠢 但从早上开始我就无法纠正这个突然出现在我的博客网站上的错误www candidopinions in http www candidopinions in 我有一个网格视图模板 其中博客文章中的特色图像作为调整大小
  • 使用 Enzyme 测试 `React.createRef` api

    我想测试下面的类 它使用React createRef api 不过 快速搜索并没有发现任何这样做的例子 有人成功过吗 我该如何嘲笑裁判 理想情况下我想使用shallow class Main extends React Component
  • react-native - 图像需要来自 JSON 的本地路径

    你好社区 我正在react native中开发一个测试应用程序 并尝试从本地存储位置获取图像 我实际在做什么 我将图像直接链接源提供给 var 并在渲染函数中调用此方法 react 0 14 8 react native 0 23 1 np
  • 在 iOS 7 Safari 中,如何区分通过边缘滑动与后退/前进按钮的 popstate 事件?

    在 iOS 7 Safari 中 现在有两种后退 前进导航方式 使用底部的传统后退 前进按钮箭头或从屏幕边缘滑动 我正在使用动画在 ajax 应用程序中的页面之间进行转换 但如果用户通过边缘滑动进行导航 我不想触发该转换 因为这本身就是一个
  • 仅当显式选择行时才关闭 ui-bootstrap typeahead

    我创建了这个jsBin http jsbin com livuqafe 2 edit来证明我遇到的问题 如果您转到此处 请尝试输入 五 并继续 你的自然反应是输入 五 然后按 Tab 如果你想要 五百 你可以向下箭头一次 但是 在这种情况下

随机推荐