openssl AF_ALG引擎使用

news2024/11/13 14:47:24

cmd

AF_ALG是Linux提供的一种虚拟接口,用于访问内核中的加密算法。在Linux中,可以使用AF_ALG接口配合加密算法框架(Crypto API)来进行加密操作。

以下是一个使用AF_ALG和openssl进行加密操作的例子:

# 加密
openssl engine -t afalg -k afalg -c
 
# 加载AF_ALG引擎
openssl engine afalg
 
# 设置会话使用的加密算法和密钥
openssl ciphers -v 'aes-128-cbc'
 
# 加密文件
openssl enc -engine afalg -aes-128-cbc -in input.txt -out output.txt -pass pass:YOUR_PASSWORD

在这个例子中,我们首先加载AF_ALG加密引擎。然后,我们设置会话使用的加密算法为AES-128-CBC。最后,我们使用openssl的enc命令进行加密操作,指定输入文件input.txt和输出文件output.txt,并使用密钥mysecretkey进行加密。

注意:在使用AF_ALG引擎之前,你需要确保系统中已经安装了libafalg-dev包,并且你的内核支持AF_ALG。

这只是一个基本的示例,实际使用时可能需要根据具体的加密算法和系统配置进行调整。

测试实例:(这是在101编译服务器环境上测试的)

der@somewhere:~/tmp/tmp$ openssl engine -t afalg -k afalg -c
engine: Cannot mix flags and engine names.
engine: Use -help for summary.
der@somewhere:~/tmp/tmp$ openssl engine -t afalg -k afalg
engine: Cannot mix flags and engine names.
engine: Use -help for summary.
der@somewhere:~/tmp/tmp$ openssl engine -t afalg
(afalg) AFALG engine support
     [ available ]
der@somewhere:~/tmp/tmp$ 
der@somewhere:~/tmp/tmp$ 
der@somewhere:~/tmp/tmp$ openssl engines
Invalid command 'engines'; type "help" for a list.
der@somewhere:~/tmp/tmp$ openssl engine
(rdrand) Intel RDRAND engine
(dynamic) Dynamic engine loading support
der@somewhere:~/tmp/tmp$ openssl engine afalg
(afalg) AFALG engine support
der@somewhere:~/tmp/tmp$ openssl ciphers -v 'aes-128-cbc'
TLS_AES_256_GCM_SHA384  TLSv1.3 Kx=any      Au=any  Enc=AESGCM(256) Mac=AEAD
TLS_CHACHA20_POLY1305_SHA256 TLSv1.3 Kx=any      Au=any  Enc=CHACHA20/POLY1305(256) Mac=AEAD
TLS_AES_128_GCM_SHA256  TLSv1.3 Kx=any      Au=any  Enc=AESGCM(128) Mac=AEAD
der@somewhere:~/tmp/tmp$
der@somewhere:~/tmp/tmp$ find /usr/lib -name "*afalg*"
/usr/lib/x86_64-linux-gnu/engines-1.1/afalg.so
der@somewhere:~/tmp/tmp$
der@somewhere:~/tmp/tmp$ openssl enc -engine afalg -aes-128-cbc -in info.txt -out output.txt
engine "afalg" set.
enter aes-128-cbc encryption password:
Verifying - enter aes-128-cbc encryption password:
*** WARNING : deprecated key derivation used.
Using -iter or -pbkdf2 would be better.
der@somewhere:~/tmp/tmp$
der@somewhere:~/tmp/tmp$ 
der@somewhere:~/tmp/tmp$ openssl enc -d -engine afalg -aes-128-cbc -in output.txt -out dec.txt -pass pass:somepasswd
engine "afalg" set.
*** WARNING : deprecated key derivation used.
Using -iter or -pbkdf2 would be better.
der@somewhere:~/tmp/tmp$ 
der@somewhere:~/tmp/tmp$ md5sum info.txt dec.txt 
c50829378ad3f6ad668b290ef8b17cc4  info.txt
c50829378ad3f6ad668b290ef8b17cc4  dec.txt
der@somewhere:~/tmp/tmp$

code

加载

int main() {
        int ret = 1;
        int type = 0;
        do{
                printf("please choose type: 0:exit 1:load_builtin, 2:init_crypto AFALG, 3:init_crypto DYNAMIC, 4:add_all_algorithms\n");
                (void)scanf(" %d",&type);
                switch(type){
                        case 0:
                                return 0;
                        case 1:
                                ENGINE_load_builtin_engines();
                                break;
                        case 2:
                                OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_AFALG, NULL);
                                break;
                        case 3:
                                OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_DYNAMIC, NULL);
                                break;
                        case 4:
                                OpenSSL_add_all_algorithms();
                                break;

                }

                ENGINE *e = ENGINE_by_id("afalg");
                if (e == NULL) {
                        printf("Can not load AFALG engine.\n");
                        continue;
                }
                printf("Load AFALG engine OK.\n");
                int rc = ENGINE_init(e);
                if (rc == 0) {
                        printf("Init AFALG engine fail.\n");
                        ENGINE_free(e);
                        continue;
                }
                printf("Init AFALG engine OK.\n");

                //now we can use afalg engine

第1种第3种可以加载,2,4种不行

使用

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/evp.h>
#include <openssl/engine.h>

// colors used in printf
#define COLOR_NONE "\033[m"
#define COLOR_RED "\033[0;32;31m"
#define COLOR_LIGHT_RED "\033[1;31m"
#define COLOR_YELLOW "\033[1;33m"
#define COLOR_GREEN "\033[0;32;32m"
#define COLOR_BLUE "\033[0;32;34m"
#define COLOR_PURPLE "\033[0;32;35m"

// switch of printf
#if 1
#define PRINT(...) printf(__VA_ARGS__)
#else
#define PRINT(...)
#endif

#if 0
#define PRINTSUCCESS(...) printf(__VA_ARGS__)
#else
#define PRINTSUCCESS(...)
#endif

#if 1
#define PRINTFAIL(...) printf(__VA_ARGS__)
#else
#define PRINTFAIL(...)
#endif

// macros related to break
#define FREE_NOTNULL(ptr, func_name) \
    {                                \
        if (ptr != NULL)             \
        {                            \
            func_name(ptr);          \
            ptr = NULL;              \
        }                            \
    }

#define CALL_FUNC(ret, funSentence, errCase)                                                                     \
    {                                                                                                            \
        ret = funSentence;                                                                                       \
        if (errCase)                                                                                             \
        {                                                                                                        \
            PRINTFAIL(COLOR_RED "[%s][%d] " #funSentence " fail:" #errCase "\n" COLOR_NONE, __FILE__, __LINE__); \
            break;                                                                                               \
        }                                                                                                        \
        else                                                                                                     \
        {                                                                                                        \
            PRINTSUCCESS(COLOR_GREEN "[%s][%d] " #funSentence " success\n" COLOR_NONE, __FILE__, __LINE__);      \
        }                                                                                                        \
    }

#define CALL_FUNC_WITHIOUTBREAK(ret, funSentence, errCase)                                                       \
    {                                                                                                            \
        ret = funSentence;                                                                                       \
        if (errCase)                                                                                             \
        {                                                                                                        \
            PRINTFAIL(COLOR_RED "[%s][%d] " #funSentence " fail:" #errCase "\n" COLOR_NONE, __FILE__, __LINE__); \
        }                                                                                                        \
        else                                                                                                     \
        {                                                                                                        \
            PRINTSUCCESS(COLOR_GREEN "[%s][%d] " #funSentence " success\n" COLOR_NONE, __FILE__, __LINE__);      \
        }                                                                                                        \
    }

#define CALL_FUNC_NOTNULL(ret, funSentence) \
    CALL_FUNC(ret, funSentence, ret == NULL)

#define CALL_FUNC_POSITIVE(ret, funSentence) \
    CALL_FUNC(ret, funSentence, ret <= 0)

#define CALL_NBFUNC_NOTNULL(ret, funSentence) \
    CALL_FUNC_WITHIOUTBREAK(ret, funSentence, ret == NULL)

#define CALL_NBFUNC_POSITIVE(ret, funSentence) \
    CALL_FUNC_WITHIOUTBREAK(ret, funSentence, ret <= 0)

#define BUFFER_SIZE 256

static void print_hex(const char *info, unsigned char *data, unsigned int len)
{
    printf("%s[len:%d | 0x%x]\n", info, len, len);
    for (int i = 0; i < len; i++)
    {
        printf("%02x ", data[i]);
    }
    printf("\n");
}

static int test_afalg_aes_cbc(ENGINE *engine)
{
    EVP_CIPHER_CTX *ctx = NULL;
    const EVP_CIPHER *cipher;
    unsigned char key[] = "\x06\xa9\x21\x40\x36\xb8\xa1\x5b"
                          "\x51\x2e\x03\xd5\x34\x12\x00\x06"
                          "\x06\xa9\x21\x40\x36\xb8\xa1\x5b"
                          "\x51\x2e\x03\xd5\x34\x12\x00\x06";
    unsigned char iv[] = "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30"
                         "\xb4\x22\xda\x80\x2c\x9f\xac\x41";
    /* input = "Single block msg\n"  17Bytes*/
    unsigned char in[BUFFER_SIZE] = "\x53\x69\x6e\x67\x6c\x65\x20\x62"
                                    "\x6c\x6f\x63\x6b\x20\x6d\x73\x67\x0a";
    unsigned char ebuf[BUFFER_SIZE + 32];
    unsigned char dbuf[BUFFER_SIZE + 32];
    unsigned char encresult_128[] = "\xe3\x53\x77\x9c\x10\x79\xae\xb8"
                                    "\x27\x08\x94\x2d\xbe\x77\x18\x1a\x2d";
    unsigned char encresult_192[] = "\xf7\xe4\x26\xd1\xd5\x4f\x8f\x39"
                                    "\xb1\x9e\xe0\xdf\x61\xb9\xc2\x55\xeb";
    unsigned char encresult_256[] = "\xa0\x76\x85\xfd\xc1\x65\x71\x9d"
                                    "\xc7\xe9\x13\x6e\xae\x55\x49\xb4\x13";
    unsigned char *enc_result = NULL;

    int encl, encf, decl, decf;
    int ret = 0;
    int keysize_idx = 0;
    printf("please choose key len: 0:128, 1:192, 2:256 else:128\n");
    (void)scanf(" %d", &keysize_idx);

    do
    {
        switch (keysize_idx)
        {
        case 0:
            cipher = EVP_aes_128_cbc();
            enc_result = &encresult_128[0];
            break;
        case 1:
            cipher = EVP_aes_192_cbc();
            enc_result = &encresult_192[0];
            break;
        case 2:
            cipher = EVP_aes_256_cbc();
            enc_result = &encresult_256[0];
            break;
        default:
            cipher = EVP_aes_128_cbc();
            enc_result = &encresult_128[0];
            break;
        }
        CALL_FUNC_NOTNULL(ctx, EVP_CIPHER_CTX_new())
        print_hex("src data", in, BUFFER_SIZE);
        CALL_FUNC_POSITIVE(ret, EVP_CipherInit_ex(ctx, cipher, engine, key, iv, 1))
        CALL_FUNC_POSITIVE(ret, EVP_CipherUpdate(ctx, ebuf, &encl, in, BUFFER_SIZE))
        CALL_FUNC_POSITIVE(ret, EVP_CipherFinal_ex(ctx, ebuf + encl, &encf))

        encl += encf;
        print_hex("enc data", ebuf, encl);
        // CALL_FUNC(ret,memcmp(enc_result, ebuf, BUFFER_SIZE),ret != 0)

        CALL_FUNC_POSITIVE(ret, EVP_CIPHER_CTX_reset(ctx))
        CALL_FUNC_POSITIVE(ret, EVP_CipherInit_ex(ctx, cipher, engine, key, iv, 0))
        CALL_FUNC_POSITIVE(ret, EVP_CipherUpdate(ctx, dbuf, &decl, ebuf, encl))
        CALL_FUNC_POSITIVE(ret, EVP_CipherFinal_ex(ctx, dbuf + decl, &decf))
        print_hex("dec data", dbuf, decl);

        decl += decf;
        CALL_FUNC_POSITIVE(ret, decl == BUFFER_SIZE)
        CALL_FUNC(ret, memcmp(dbuf, in, BUFFER_SIZE), ret != 0)
        printf("engine enc dec success.\n");
        ret = 1;
    } while (0);
end:
    FREE_NOTNULL(ctx, EVP_CIPHER_CTX_free)
    return ret;
}

int test_engine_digest(ENGINE *engine)
{
    int ret = 0;
    const EVP_MD *md = NULL;
    EVP_MD_CTX *emctx = NULL;
    unsigned char data[128] = {1, 2, 4};
    unsigned char digestData[64] = {0};
    unsigned int digestSize = sizeof(digestData);
    const char *eName = NULL;
    do
    {
        CALL_FUNC_NOTNULL(eName, ENGINE_get_name(engine))
        printf("engine name:%s\n", eName);
        CALL_FUNC_POSITIVE(ret, ENGINE_register_digests(engine))               //
        CALL_FUNC_POSITIVE(ret, ENGINE_set_default(engine, ENGINE_METHOD_ALL)) // ENGINE_METHOD_DIGESTS))

        CALL_FUNC_NOTNULL(emctx, EVP_MD_CTX_new())
        CALL_FUNC_POSITIVE(ret, EVP_MD_CTX_init(emctx))
        CALL_FUNC_NOTNULL(md, EVP_md5())
        digestSize = sizeof(digestData);
        CALL_FUNC_POSITIVE(ret, EVP_DigestInit_ex(emctx, md, engine))
        CALL_FUNC_POSITIVE(ret, EVP_DigestUpdate(emctx, data, sizeof(data)))
        CALL_FUNC_POSITIVE(ret, EVP_DigestFinal(emctx, digestData, &digestSize))
        print_hex("MD5 3 segment result", digestData, digestSize);

        memset(digestData, 0, sizeof(digestData));
        digestSize = sizeof(digestData);
        // CALL_FUNC_POSITIVE(ret,EVP_DigestInit_ex(emctx,md,engine))
        CALL_FUNC_POSITIVE(ret, EVP_Digest(data, sizeof(data), digestData, &digestSize, md, engine))
        print_hex("MD5 1 segment result", digestData, digestSize);

        memset(digestData, 0, sizeof(digestData));
        digestSize = sizeof(digestData);
        CALL_FUNC_NOTNULL(md, EVP_sha1())
        CALL_FUNC_POSITIVE(ret, EVP_DigestInit_ex(emctx, md, engine))
        CALL_FUNC_POSITIVE(ret, EVP_DigestUpdate(emctx, data, sizeof(data)))
        CALL_FUNC_POSITIVE(ret, EVP_DigestFinal(emctx, digestData, &digestSize))
        print_hex("SHA1 3 segment result", digestData, digestSize);

        memset(digestData, 0, sizeof(digestData));
        digestSize = sizeof(digestData);
        CALL_FUNC_NOTNULL(md, EVP_sha256())
        CALL_FUNC_POSITIVE(ret, EVP_DigestInit_ex(emctx, md, engine))
        CALL_FUNC_POSITIVE(ret, EVP_DigestUpdate(emctx, data, sizeof(data)))
        CALL_FUNC_POSITIVE(ret, EVP_DigestFinal(emctx, digestData, &digestSize))
        print_hex("SHA256 3 segment result", digestData, digestSize);
    } while (0);
    // FREE_NOTNULL(md,EVP_md5xx) //do not need free
    FREE_NOTNULL(emctx, EVP_MD_CTX_free)
    return ret;
}

int main()
{
    int ret = 1;
    int type = 0;
    do
    {
        printf("please choose type: 0:exit 1:load_builtin, 2:init_crypto AFALG, 3:init_crypto DYNAMIC, 4:add_all_algorithms\n");
        (void)scanf(" %d", &type);
        switch (type)
        {
        case 0:
            return 0;
        case 1:
            ENGINE_load_builtin_engines();
            break;
        case 2:
            OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_AFALG, NULL);
            break;
        case 3:
            OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_DYNAMIC, NULL);
            break;
        case 4:
            OpenSSL_add_all_algorithms();
            break;
        }

        ENGINE *e = ENGINE_by_id("afalg");
        if (e == NULL)
        {
            printf("Can not load AFALG engine.\n");
            continue;
        }
        printf("Load AFALG engine OK.\n");
        int rc = ENGINE_init(e);
        if (rc == 0)
        {
            printf("Init AFALG engine fail.\n");
            ENGINE_free(e);
            continue;
        }
        printf("Init AFALG engine OK.\n");

        // now we can use afalg engine
        CALL_FUNC_POSITIVE(ret, test_afalg_aes_cbc(e))
        CALL_FUNC_POSITIVE(ret, test_engine_digest(e))

        // ENGINE_free(e);
        ENGINE_finish(e);
    } while (type != 0);
    return 0;
}
der@somewhere:~/tmp/tmp/engine$ gcc -o engine engine.c -lcrypto
der@somewhere:~/tmp/tmp/engine$ ./engine 
please choose type: 0:exit 1:load_builtin, 2:init_crypto AFALG, 3:init_crypto DYNAMIC, 4:add_all_algorithms
3
Load AFALG engine OK.
Init AFALG engine OK.
please choose key len: 0:128, 1:192, 2:256 else:128
2
src data[len:256 | 0x100]
53 69 6e 67 6c 65 20 62 6c 6f 63 6b 20 6d 73 67 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
enc data[len:272 | 0x110]
a0 76 85 fd c1 65 71 9d c7 e9 13 6e ae 55 49 b4 ca 9f 86 f1 4f 52 d9 66 6c a1 f9 25 ae 42 c6 d9 e6 f2 15 3a 08 14 c2 e0 02 06 de e2 c1 45 ba 02 dc 36 85 a8 2e 74 a3 68 b8 96 69 0f 78 59 34 50 77 85 24 00 f1 54 ea 9f 75 b7 61 c1 db a1 ad b3 3b b5 c1 c9 77 9f f0 f8 fc 95 f1 36 17 34 c5 03 41 43 1e 6e 69 e8 e1 88 fb d1 ac 0c 46 6e 71 26 52 a3 91 b3 87 dc 6a 16 e4 02 a8 a4 8b 4c 6a c1 ef 5d 92 3b ab 43 cc 80 34 5a c6 52 c6 48 8b a0 f5 14 12 85 55 78 92 80 30 5f f9 45 e1 fe 61 e9 02 da a1 69 19 a1 92 16 87 f2 a3 8d e3 e8 15 34 69 c2 40 69 2b 15 43 27 da 4e 56 15 d3 10 e5 55 58 8c d0 0e ee 2b 3f 00 57 e8 65 7f ac d5 01 af 9a 13 1a c0 ae ac b1 a8 01 46 f7 15 2d 26 22 b1 87 a0 ee db a3 fb 9d a3 94 77 91 e1 72 25 5e 9c 17 d6 d6 5f e9 3c 2f 0f bb be 79 1f 99 06 7e 37 68 67 9c 76 04 dc de e3 dc ed dd c9 32 fd dc 7d 
dec data[len:256 | 0x100]
53 69 6e 67 6c 65 20 62 6c 6f 63 6b 20 6d 73 67 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
engine enc dec success.
engine name:AFALG engine support
[engine.c][197] EVP_DigestInit_ex(emctx,md,engine) fail:ret <= 0
[engine.c][271] test_engine_digest(e) fail:ret <= 0
der@somewhere:~/tmp/tmp/engine$ 
der@somewhere:~/tmp/tmp/engine$

可以看到aes使用afalg引擎成功,但是digest使用引擎失败了。之前好像看到过说明,digest软算法很快,如果使用硬件加速引擎综合开销反而更大或者效率提升不明显,如果需要引擎支持digest需要编译openssl的时候指定相应标志。就这样。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1546293.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot—@ConditionalOnBean与@ConditionalOnClass

一、ConditionalOnBean概念 需求场景 比如下面一种场景&#xff0c;我在实例化People对象的时候&#xff0c;需要注入一个City对象。这个时候问题来了&#xff0c;如果city没有实例化&#xff0c;那么下面就会报空指针或者直接报错。 所以这里需求很简单&#xff0c;就是当前c…

服务运营|香港大学雷骁:收益管理中价格歧视的公平性

编者按&#xff1a; INFORMS George B. Dantzig Dissertation Award 用于表彰运筹学和管理科学领域中具有创新性和实用性的最佳毕业设计。香港大学助理教授雷骁题为“Revenue Management in Video Games and With Fairness” 是这一奖项2023年度的提名者之一。 这篇毕业设计重…

利用AI技术预测未被充分监测的流域中的极端洪水事件笔记

利用人工智能&#xff08;AI&#xff09;技术预测未被充分监测的流域&#xff08;ungauged watersheds&#xff09;中的极端洪水事件 文章目录 利用人工智能&#xff08;AI&#xff09;技术预测未被充分监测的流域&#xff08;ungauged watersheds&#xff09;中的极端洪水事件…

bsd猜想 Murmuration of Eliptic Curves(笔记)

BSD Alexey Pozdnyakov (University of Connecticut) YUTUBE视频&#xff0c; B站搬运地址新生代女数学家Nina Zubrilina得到椭圆曲线椋鸟群飞模式精确公式与证明 Arithmetic Geometry算术几何 希尔伯特第十问题 希尔伯特第十问题&#xff08;Hilbert’s Tenth Problem&#…

TransUNet论文笔记

论文&#xff1a;TransUNet&#xff1a;Transformers Make Strong Encoders for Medical Image Segmentation 目录 Abstract Introduction Related Works 各种研究试图将自注意机制集成到CNN中。 Transformer Method Transformer as Encoder 图像序列化 Patch Embed…

拼板注意事项和步骤

拼板注意事项和步骤 综述&#xff1a;本文讲述了AD软件中拼板的注意事项以及拼板的步骤。 1. 拼板注意事项 拼板时应注意定位孔、光学定位点、工艺边、间距和器件冲突等问题。 2. 拼板步骤 ①点击“放置”→“拼板阵列”→“panels”→“properties”&#xff0c;浏览需要…

晴问算法 动态规划(简单)

动态规划的递归写法和递推写法 斐波那契数列II 题目描述 给定正整数&#xfffd;&#xff0c;求斐波那契数列的第&#xfffd;项&#xfffd;(&#xfffd;)。 令&#xfffd;(&#xfffd;)表示斐波那契数列的第&#xfffd;项&#xff0c;它的定义是&#xff1a; 当&…

【MD】激光驱动原子动力学的全尺寸从头算模拟

Zeng Q, Chen B, Zhang S, et al. Full-scale ab initio simulations of laser-driven atomistic dynamics[J]. npj Computational Materials, 2023, 9(1): 213.核心研究内容&#xff1a; 本文研究了激光驱动的原子动力学的全尺度从头算模拟。研究的重点是探讨在极端条件下材料…

C语言结构体之位段

位段&#xff08;节约内存&#xff09;&#xff0c;和王者段位联想记忆 位段是为了节约内存的。刚好和结构体相反。 那么什么是位段呢&#xff1f;我们现引入情景&#xff1a;我么如果要记录一个人是男是女&#xff0c;用数字0 1表示。我们发现只要一个bit内存就可以完成我们想…

讯优随身WiFi可靠吗?讯优和格行随身WiFi哪个好?随身wifi推荐测评!随身WiFi哪个牌子比较好用?随身WiFi怎么选?随身WiFi推荐第一名!

随身WiFi挑花眼&#xff1f;不知道哪款好用&#xff1f;今天&#xff0c;我将为大家带来迅优与格行两大随身WiFi品牌的真实测评。 价格方面&#xff1a;迅优随身WiFi以价格优惠为卖点&#xff0c;吸引了众多消费者的目光。对于预算有限的用户来说&#xff0c;迅优确实提供了一个…

刷题记录:最长公共前缀

编写一个函数来查找字符串数组中的最长公共前缀。 如果不存在公共前缀&#xff0c;返回空字符串 ""。 示例 1&#xff1a; 输入&#xff1a;strs ["flower","flow","flight"] 输出&#xff1a;"fl"示例 2&#xff1a; 输…

治疗植物神经功能紊乱的关键竟是它!

植物神经紊乱&#xff0c;是指交感神经系统和副交感神经系统之间的平衡失调&#xff0c;导致心率不规律、胃肠问题、焦虑、失眠等一系列症状。长期植物神经紊乱可能导致更严重的心血管疾病、消化系统问题以及心理健康隐患。它可能源于饮食结构失衡、物理环境压力过大、心理压力…

Xinstall:用智能数据传递,打造高效的App推广体系

随着移动互联网的快速发展&#xff0c;App已经成为人们日常生活中不可或缺的一部分。然而&#xff0c;对于开发者来说&#xff0c;如何有效地推广App并衡量推广效果却是一个巨大的挑战。这时&#xff0c;Xinstall作为一站式App全渠道统计服务商&#xff0c;提供了强有力的解决方…

模板(一)

文章目录 模板&#xff08;一&#xff09;1.泛型编程2.函数模板2.1函数模板概念2.2函数模板格式2.3函数模板的原理2.4函数模板的实例化2.4.1隐式实例化2.4.2显式实例化 2.5模板参数的匹配原则 3.类模板3.1类模板的定义格式3.2类模板的实例化 模板&#xff08;一&#xff09; 1…

25.7 MySQL 数据库和表的基本操作

1. 基础知识 1.1 一条数据的存储过程 存储数据确实是处理数据的基石, 只有确保数据被准确无误且有条理地存储, 我们才能对其进行深入的处理和细致的分析. 否则, 这些数据就像是一团毫无章法的乱麻, 让我们难以捉摸其内在的逻辑和价值.那么, 如何才能够将用户那些与经营紧密相关…

人工智能时代如何高效完成营销内容计划

智能对话升级&#xff01;【Kompas AI】AI对话助手&#xff0c;让沟通更高效 在人工智能时代&#xff0c;要高效完成营销计划&#xff0c;我们可以利用人工智能的多种能力来增强营销策略的精准度和执行效率。借助人工智能的力量&#xff0c;企业不仅可以提高营销计划的执行效率…

Rust高级爬虫:如何利用Rust抓取精美图片

引言 在当今信息爆炸的时代&#xff0c;互联网上的图片资源丰富多彩&#xff0c;而利用爬虫技术获取这些图片已成为许多开发者的关注焦点。本文将介绍如何利用Rust语言进行高级爬虫编程&#xff0c;从而掌握抓取精美图片的关键技术要点。 Rust爬虫框架介绍 Rust语言生态中有…

一文说清:AI大模型在制造业中的应用类型

在过去的几年里&#xff0c;全球制造业的竞争格局正在发生重构&#xff0c;数字化和智能化成为推动变革的关键力量。AI 大模型作为一种通用人工智能技术&#xff0c;其革命性特征体现在能够生成代码、构建人机交互新模式&#xff0c;并与产品研发、工艺设计、生产作业、产品运营…

2024软考

报考链接&#xff1a; 中国计算机技术职业资格网 (ruankao.org.cn) 报名有效时间&#xff1a; 天津2024-03-24 09:00 ~ 2024-04-02 17:00 河北2024-03-20 09:30 ~ 2024-03-26 17:00 山西2024-03-18 14:30 ~ 2024-04-02 11:30 宁波2024-03-20 10:00 ~ 2024-03-26 16:00 辽宁…

C语言调用云端 Python接口

利用C语言调用阿里云Python接口&#xff0c;来实现垃圾的智能识别 文章目录 利用C语言调用阿里云Python接口&#xff0c;来实现垃圾的智能识别1、如何开启阿里云服务2、实验程序介绍2.1 py程序改造2.2 c语言调用py2.3 测试代码 3、实验结果 1、如何开启阿里云服务 大家可以自行…