Notice: Function wp_enqueue_script was called incorrectly. Scripts and styles should not be registered or enqueued until the wp_enqueue_scripts, admin_enqueue_scripts, or login_enqueue_scripts hooks. This notice was triggered by the jquery handle. Please see Debugging in WordPress for more information. (This message was added in version 3.3.0.) in /mnt/webroot/wandoer/code.wandoer/wp-includes/functions.php on line 6260
RyanWong – 第 5 页 – 豌豆

作者: RyanWong

  • 跨平台工程构建:CMake 的使用 (一)

    什么是 CMake

    当我们在构建工程时,在不同的平台上使用不同的工具,如在Windows上使用 Visual Studio 工程, 在 Mac 上使用 Xcode 工程。

    这些工程只限于特定的平台。当我们需要跨平台构建工程时,就需要使用 CMake 了,它是一个开源的 跨平台系统构建工具 。同一个 CMake 工程可以在不同的平台上转换为与平台适应的工具,极大的方便了跨平台工程构建。

    第一个 CMake

    新建一个空目录,在其中新建一个文本文件,命名为 CMakeLists.txt,并输入以下内容:

    message("Hello,This is my first cmake project")

    好了,你的第一个 cmake 工程就已经建好了。接下来,新建一个文件夹 build, 并在该文件夹下运行命令:

    cmake ..

    你可能会得到以下输出:

    -- Building for: Visual Studio 15 2017
    -- The C compiler identification is MSVC 19.15.26732.1
    -- The CXX compiler identification is MSVC 19.15.26732.1
    -- Check for working C compiler: ....../cl.exe
    -- Check for working C compiler: ....../cl.exe -- works
    -- Detecting C compiler ABI info
    -- Detecting C compiler ABI info - done
    -- Check for working CXX compiler: ....../cl.exe
    -- Check for working CXX compiler: ....../cl.exe -- works
    -- Detecting CXX compiler ABI info
    -- Detecting CXX compiler ABI info - done
    -- Detecting CXX compile features
    -- Detecting CXX compile features - done
    Hello,This is my first cmake project
    -- Configuring done
    -- Generating done
    -- Build files have been written to: ....../build

    再来看这个路径下,cmake 生成了一堆文件:

    我们成功的使用 cmake 在 Windows 上构建了一个 vs 工程。 当然,如果你的操作系统是 MacOS, 或者 Linux, 结果后有所不同。

    其实在 CMakeLists.txt 所以在路径下也能运行 cmake 命令。不过cmake没有提供专门的工具来清理生成的文件,为了方便管理,我们将其生成在 build 目录下。

    这个 cmake 工程的作用仅仅是输出一了条消息,并没有什么意义。下面我们来让它更有意义一点:

    (更多…)

  • 使用 openssl 进行椭圆曲线加解密(SM2)

    在之前一篇博客 ECC(Elliptic Curves Cryptography) 椭圆曲线加密原理 简单地阐述了 ECC 加解密的原理。这本篇博客中接着来聊一聊如何使用 OPENSSL 来进行 ECC 加解密。

    首先需要明确一点的是:ECC 本身并没有定义一套加解密的方法,它主要作用于密钥交换(ECDHE),与签名认证(ECDSA). 不过后来中国工程师设计定义了一套加密方法,并于近年得到了世界的认可,这就是中国商用(国家标准) SM2 椭圆曲线公钥密码算法 。

    一. 基本概念

    其实在 openssl 中,椭圆曲线分两种形式,一种是之前讲到的质数域上的椭圆曲线 ,将其称为 $F_p$ 其方程为:

    $$y^2 \ \mod \ p = x^3 + ax + b \ \mod \ p$$

    另一种是二进制域,称为 $F_{2^m}$, 其方程为:

    $$y^2  + xy = x^3 + ax^2 + b ,\  (b != 0)$$

    在这里只讨论 $F_p$ 相关的内容。

    椭圆曲线上的点

    椭圆曲线上的点使用 EC_POINT 来表示, 它定义在 ec_locl.h :

    struct ec_point_st {
        // ...
        BIGNUM *X;
        BIGNUM *Y;
        BIGNUM *Z;
        // ...
    };

    (更多…)

  • 使用 openssl 进行 DH 密钥交换

    在我之前的博客中聊到了 DH 密钥交换的原理 . 这里来讨论如何使用 OPENSSL 进行 DH 密钥交换。

    一 原理验证

    OPENSSL 提供了一系列API, 可以在方便地进行大数计算。在这里我们先对 DH 密钥交换的原理 中讲到的原理进行代码级别的验证。对原理不感兴趣的可以跳过这一小节。
    由于在 DH 密钥交换过程中,大部分的操作过程都是一样的,可以定义一个基类来抽象:

    class DHBase {
    public:
        DHBase() : m_pri_key(NULL) {}
    
        virtual ~DHBase() {
            if (m_pri_key)
                BN_free(m_pri_key);
        };
    
        const BIGNUM *GetSharedNum() {
            if (!m_pri_key)
                GenRandomData();
    
            BN_CTX *ctx = BN_CTX_new();
            const BIGNUM *g = DH_get0_g(m_dh);
            const BIGNUM *p = DH_get0_p(m_dh);
            BIGNUM *r = BN_new();
    
            // r = g ^ m_pri_key % p
            int rst = BN_mod_exp(r, g, m_pri_key, p, ctx);
            assert(rst == 1);
            BN_CTX_free(ctx);
            return r;
        }
    
        BIGNUM *GenKey(const BIGNUM *shared_num) {
            if (!m_pri_key)
                GenRandomData();
    
            BIGNUM *key = BN_new();
            BN_CTX *ctx = BN_CTX_new();
    
            // key = shared_num ^ m_pri_key % p
            int rst = BN_mod_exp(key, shared_num, m_pri_key, DH_get0_p(m_dh), ctx);
            assert(rst == 1);
            BN_CTX_free(ctx);
    
            std::cout << m_name << ": received shared num: " << GetNumString(shared_num) << std::endl;
            std::cout << m_name << ": generated KEY: " << GetNumString(key) << std::endl;
            return key;
        }
    
        std::string GetName() {
            return m_name;
        }
    
        static std::string GetNumString(const BIGNUM *num) {
            return BN_bn2hex(num);
        }
    
    private:
        void GenRandomData() {
            assert(m_dh);
            m_pri_key = BN_new();
            int rst = BN_rand_range(m_pri_key, DH_get0_p(m_dh));
            assert(rst == 1);
            while (BN_is_zero(m_pri_key)) {
                BN_rand_range(m_pri_key, DH_get0_p(m_dh));
            }
            std::cout << m_name << ": generated the private num" << std::endl;
        }
    
    protected:
        DH *m_dh;
        std::string m_name;
    
    private:
        BIGNUM *m_pri_key;
    };
    • m_pri_key 是双方生成的私密随机数。
    • GetSharedNum() 返回双方交换的中间变量 G^A mod P
    • GenKey() 即完成了密钥交换,返回交换成功后的密钥。

    (更多…)

  • 使用 openssl 进行 RSA 加解密

    在我之前的一篇博客中 RSA 公钥加密原理 中, 对 RSA 非对称加密原理做了简单的阐述。这篇博客主要聊如何使用 OPENSSL 进行密钥对的生成,以及非对称加解密。

    一. 生成密钥对

    在 OPENSSL 中, RSA 是一个很重要的结构体。它的定义在 rsa_locl.h 中,面包含了在原理中提到的所有重要的变量 随机质数 p, q, 公钥指数 e, 私钥指数 d, 以及模数 n

    struct rsa_st {
     // ...
        BIGNUM *n;
        BIGNUM *e;
        BIGNUM *d;
        BIGNUM *p;
        BIGNUM *q;
     // ...
    };

    生成密钥函数:

    int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb);
    • bits 密钥的规模(modulus)。小于 1028 位的密钥是不安全的,小于 512 则会返回 0
    • e 公开的指数。它应该是一个奇数(odd number), 一般是 3, 17 或 65537
    • cb 生成大随机数的回调函数。一般使用 NULL 即可, 默认为 BN_GENCB_call()

    (更多…)

  • 使用 openssl 进行 AES 加解密

    在我之前的一篇博客里介绍了 对称加密的模式 . 这里主要聊一聊如何使用 openssl 来进行 AES 加密 .

    一. OPENSSL crypto API

    openssl 加密 API 分两个部分: High Level and Low Level . 对于大部分人来说,使用 High Level 就够用了, 这些 API 被冠以 EVP (Envelope) ,表示对 Low Level 的封装。High Level API 提供了包括 对称/非对称加解密 , 签名, 验证, 哈希,MAC 等一系列组件,屏蔽了 Low Level API 的复杂逻辑,使用起来安全高效。对于除非有需要进行加密算法级别的改进,否则不建议使用 Low Level API.
    大部分 EVP API 有一个 int 型返回值 ,用来表示操作是否成功:1 表示成功, 0 表示失败。但有些时候也会返回 -1 ,表达如内存分配或者其他什么错误。官方指导代码如下:

        if(1 != EVP_xxx()) goto err;
        if(1 != EVP_yyy()) goto err;
    
        /* ... do some stuff ... */
    
    err:
        ERR_print_errors_fp(stderr);

    二. 使用 EVP API 进行 AES 加解密

    对于 AES 加解密,EVP API 分为两种,EVP_Encrypt / EVP_Decryp 系列 和 EVP_Cipher 系列。后者是对前者进一步的封装。它们具体使用的套路都是一样的:

    1. 创建加解密上下文 EVP_CIPHER_CTX
    2. 调用 xxxInit() 函数,使用 key(密钥)、iv(前置向量) 和 cipher(算法) 对上下文初始化
    3. 调用 xxxUpdate() 函数进行加解密。该函数支持流式操作。即对于一段明文来说,分成多组按顺序进行加密,和一次性全部加密,不影响其生成的密文的正确性。
    4. 调用 xxxFinal() 函数获取上下文中遗留的信息
    5. 释放上下文, 完成加解密。

    (更多…)

  • MacOS mojave 接外设时无法连接 wifi 的问题

    昨天为我的rmbp配了一个外接显示器,今天突然发现mac无法连接wifi了,整个下午尝试了包括重启路由器、重置路由器、更换各种wifi参数、重启电脑等等一系列操作,均无法解决。

    偶然在网上发现有人说拔掉 U 盘/ type-c 设备 / 移动硬盘等外设可以解决这个问题,我尝试断开外接显示器,果然一下子连上了wifi。如果wifi和显示器只能二选一,那我的显示器岂不是白买了,在 google 上查找度尝试,最终找到几种对我有效的方法:

    一 删除设置缓存

    1. 关闭wifi

    2. 重启电脑  以确保所有用到网络的应用程序都关闭了

    3. 删除相关文件  需要先备份  /Library/Preferences/SystemConfiguration 下所有的文件,再将该文件夹删除

    4. 重启电脑

    5. 打开wifi

    这种方法不是对每个人都有效。另外操作前最好先备份一下重要资料。

    二、改变外设位置

    第一种方法并不是每次都管用。偶尔还得重新弄一回。后来发现:

    当外设处于 Mac 的正左侧或正右侧是,断网现在最为明显。当外设位于 Mac 的前侧或后侧时,网速最好。

    三、Mac 外壳接地

    无意中发现手触到 Mac 某些地方时,连网突然恢复,可能是人体接地使 Mac 天线发生了变化。多次实验当手接触到这两个位置时,信号最好:

    想办法让这两个地方接地就可

     

  • RSA 公钥加密原理

    和对称加密不同,公钥加密(非对称加密)的密钥分为加密密钥(公钥)和解密密钥(私钥)。 公钥是公开的,任何人都有可能知道公钥,并用公钥生成密文,而私钥是保密的,只有解密者才能知道私钥,用它来解密密文获得明文。在这里对使用最广泛的公钥密码算法– RSA.
    RSA 是发明此算法的三位科学家的姓氏的首字母(吐槽一下:外国人的命名真随意)

    一. RSA 加密

    在RSA中,明文,密钥和密文都是数字, RSA的加密过程可以用如下公式表达:

    $$密文 = 明文^E  \mod N$$

    即: RSA  的密文是明文的 $E$ 次方求模 $N$ 的结果, 或者说,密文是明文的 $E$ 次方除以 $N$ 的余数。这就是整个加密过程,它非常简洁。因此,如果知道了 $E$ 和 $N$ ,那么任何人都可以进行加密运算,也就是说,

    $$ E 和 N 是公钥$$

    在实际使用中, E 和 N 是经精心计算的数字。

    二. RSA 解密

    RSA 解密公式如下:

    $$ 明文= 密文^D \mod N$$

    即,对密文的 $D$ 次方求模 $N$ 运算,就可以得到明文。这里是

    $$D 和 N 是私钥 $$

    (更多…)

  • Diffie-Hellman 密钥交换

    在使用对称加密中,有一些无法避免的问题:

    • 密钥如何从加密方传递给解密方。窃听者如果可以劫获密文,那么也可能劫获密钥。
    • 如果窃听者破解了密钥,加密方如何将新的密钥安全地交给解密方

    1. DH 密钥交换

    解决上述问题的一种方法就是 DH 密钥交换 技术 。
    DH 密钥交换全称为 Diffie-Hellman 密钥交换 ,是1976年由 Whitfiedl Diffle 和 Martin Hellman 共同发明的一种算法。使用这种方法,通信双方可以在窃听者眼皮子底下来安全地传输密码。
    DH 交换的步骤如下:

    (更多…)