Go语言加密技术实战:掌握encoding/pem库

news2024/11/18 6:19:38

Go语言加密技术实战:掌握encoding/pem库

    • 引言
    • PEM格式简介
      • 核心组成
      • 常见用途
    • Go语言的`encoding/pem`库概览
      • 核心功能
      • 使用场景
    • 开始使用`encoding/pem`
      • 读取PEM文件
      • 编码为PEM格式
    • 深入理解PEM编码
      • 自定义PEM头部信息
    • 使用`encoding/pem`解码PEM文件
    • PEM文件的加密与解密
      • 加密私钥并保存为PEM格式
      • 从PEM格式解密私钥
    • 高级应用场景
      • 证书链的处理
      • 生成自签名证书
    • 常见问题与解答
      • Q1: 如何处理`pem.Decode`返回nil的情况?
      • Q2: 在使用`encoding/pem`库处理加密PEM文件时,如何选择合适的加密算法?
      • Q3: 生成的PEM文件在其他语言或工具中无法识别,原因可能是什么?
      • Q4: 如何将PEM文件转换为其他格式,如DER?
      • Q5: 在处理大量的PEM文件时,有没有性能优化的建议?
    • 结语

在这里插入图片描述

引言

在现代软件开发中,安全性是一个永恒的主题。特别是在数据传输和存储过程中,加密技术的应用成为了保障数据安全不可或缺的一环。PEM(Privacy Enhanced Mail)格式作为一种广泛使用的证书格式,其在安全领域的重要性不言而喻。它不仅支持数字证书的传输和存储,还能够保障数据的完整性和可靠性。因此,深入了解PEM格式及其在Go语言中的应用,对于每一位致力于提高软件安全性的开发者来说,都是一项必不可少的技能。

在接下来的内容中,我们将通过详实的代码示例和深入浅出的解析,全面介绍Go语言标准库encoding/pem的使用方法。无论你是初次接触PEM格式,还是希望在现有基础上进一步提升自己的开发技能,相信本文都能为你提供有价值的参考和帮助。

PEM格式简介

PEM(Privacy Enhanced Mail)格式最初设计用于加密邮件,以提高电子邮件通信的安全性。随着时间的发展,这种格式逐渐被广泛应用于各种场景中,尤其是在数字证书和各类密钥的存储与交换中。PEM格式的文件通常包含一段或多段以"-----BEGIN…“开头,以”-----END…"结尾的文本,这些文本之间包含的是Base64编码的数据。

核心组成

PEM文件的核心组成部分包括:

  • 类型标头:指明了PEM文件中编码数据的类型,如CERTIFICATERSA PRIVATE KEY等。
  • Base64编码数据:实际的二进制数据经过Base64编码后的文本形式。
  • 可选的头部信息:有些PEM文件可能包含额外的头部信息,用于提供编码数据的额外信息,比如加密算法等。

常见用途

  • 数字证书:PEM格式是存储和分发数字证书的常用格式,包括SSL/TLS证书和个人证书等。
  • 密钥:公钥和私钥也常以PEM格式存储,以便于在不同的系统和应用之间交换。
  • 证书签名请求(CSR):在申请数字证书时,需要提交CSR,它通常也是以PEM格式提供。

通过掌握PEM格式的基础知识和应用场景,开发者可以更好地理解和使用Go语言中的encoding/pem库来处理相关任务。接下来,我们将深入探讨如何通过encoding/pem库来执行这些操作,从简单的读取PEM文件到处理更复杂的加密PEM文件等。

接下来,我们将深入探讨Go语言中的encoding/pem库,了解它的基本功能和如何在实际开发中应用这个库。

Go语言的encoding/pem库概览

Go语言的encoding/pem库提供了简单易用的接口,用于编码和解码PEM编码的数据。这个库主要处理的是将二进制数据转换为PEM格式的文本数据,以及将PEM格式的文本数据还原为二进制数据。使用这个库,开发者可以轻松地在Go应用程序中处理数字证书、密钥以及其他PEM格式的数据。

核心功能

encoding/pem库主要提供了以下几个核心功能:

  • 编码pem.Encodepem.EncodeToMemory函数允许开发者将二进制数据编码为PEM格式的数据。
  • 解码pem.Decodepem.DecodeToMemory函数用于解码PEM格式的数据,还原为原始的二进制数据。
  • 处理加密PEM数据:库中还包含了处理加密PEM数据的功能,允许开发者在需要密码才能访问的情况下,对PEM格式的密钥或证书进行编码和解码。

使用场景

在实际开发中,encoding/pem库的使用场景非常广泛,包括但不限于:

  • 证书管理:在处理SSL/TLS通信和设置HTTPS服务器时,经常需要读取和解析PEM格式的证书文件。
  • 密钥的读取和存储:无论是公钥还是私钥,开发者都可以使用encoding/pem库来读取、生成或转换PEM格式的密钥文件。
  • 安全通信:在构建安全的通信协议时,encoding/pem库可以用于交换和验证数字证书,确保通信双方的身份和数据的安全性。

在接下来的部分,我们将通过实际的代码示例,详细介绍如何使用encoding/pem库来处理PEM格式的数据。从基本的读取和编码操作,到更高级的加密数据处理,我们将一步步深入探索encoding/pem库的强大功能。

开始使用encoding/pem

在Go语言中使用encoding/pem库处理PEM格式的数据是直接且简单的。本节将通过实际的代码示例,展示如何读取和编码PEM文件。首先,我们需要了解如何读取一个PEM文件,这是最常见的操作之一。

读取PEM文件

假设我们有一个包含私钥的PEM文件private.pem,以下示例展示了如何使用encoding/pem库读取该文件:

package main

import (
    "encoding/pem"
    "io/ioutil"
    "log"
)

func main() {
    // 读取PEM文件
    pemData, err := ioutil.ReadFile("private.pem")
    if err != nil {
        log.Fatal(err)
    }

    // 使用pem.Decode解码PEM数据
    block, _ := pem.Decode(pemData)
    if block == nil {
        log.Fatal("failed to parse PEM block containing the key")
    }

    // 输出block的类型,比如"RSA PRIVATE KEY"
    log.Printf("Type of the key: %s\n", block.Type)
}

这个例子展示了如何读取一个PEM格式的私钥文件,并解码以获取其中的信息。pem.Decode函数返回一个*pem.Block结构,包含了PEM数据块的类型、头部信息以及原始的二进制数据。

编码为PEM格式

将数据编码为PEM格式同样简单。以下是一个如何将一个密钥编码为PEM格式并保存到文件的例子:

package main

import (
    "encoding/pem"
    "crypto/rand"
    "crypto/rsa"
    "crypto/x509"
    "encoding/pkcs8"
    "os"
)

func main() {
    // 生成RSA密钥
    privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
    if err != nil {
        panic(err)
    }

    // 将密钥转换为PKCS#8格式
    privBytes, err := x509.MarshalPKCS8PrivateKey(privateKey)
    if err != nil {
        panic(err)
    }

    // 创建PEM块
    privPem := &pem.Block{
        Type:  "PRIVATE KEY",
        Bytes: privBytes,
    }

    // 写入文件
    pemFile, err := os.Create("private.pem")
    if err != nil {
        panic(err)
    }
    defer pemFile.Close()
    pem.Encode(pemFile, privPem)
}

这段代码首先生成了一个RSA密钥,然后将其转换为PKCS#8格式,并最终编码为PEM格式写入文件。通过这种方式,开发者可以轻松地在Go程序中生成、编码和存储密钥。

接下来,我们将深入探讨PEM编码的过程,以及如何使用Go语言的encoding/pem库处理加密的PEM文件。这一部分对于理解如何在实际应用中安全地管理和传输敏感数据尤为重要。

深入理解PEM编码

PEM编码的核心是将二进制数据转换为一种可读的文本格式,这种格式包括一个明确的类型标头和Base64编码的数据体。这样的设计旨在使得PEM文件易于传输和存储,同时保持了数据的完整性和可识别性。

自定义PEM头部信息

在一些高级应用场景中,你可能需要在PEM编码的数据中添加自定义的头部信息。这可以通过修改pem.Block结构体中的Headers字段来实现,如下所示:

package main

import (
    "encoding/pem"
    "os"
)

func main() {
    // 创建一个包含自定义头部信息的PEM块
    block := &pem.Block{
        Type:    "MY CUSTOM TYPE",
        Headers: map[string]string{"Header1": "Value1", "Header2": "Value2"},
        Bytes:   []byte("your data here"),
    }

    // 将PEM块编码并写入文件
    file, err := os.Create("custom.pem")
    if err != nil {
        panic(err)
    }
    defer file.Close()
    if err := pem.Encode(file, block); err != nil {
        panic(err)
    }
}

此代码段创建了一个pem.Block,其中包含自定义的类型和头部信息,并将其编码为PEM格式写入文件。这种方式允许开发者在PEM文件中嵌入额外的元数据,为数据处理提供更多的上下文信息。

使用encoding/pem解码PEM文件

解码PEM文件是理解其内容和执行相关操作的第一步。以下示例展示了如何解码PEM格式的数据,并读取其中的信息:

package main

import (
    "encoding/pem"
    "io/ioutil"
    "log"
)

func main() {
    // 读取PEM文件
    pemData, err := ioutil.ReadFile("example.pem")
    if err != nil {
        log.Fatal(err)
    }

    // 循环解码所有PEM数据块
    var block *pem.Block
    for {
        block, pemData = pem.Decode(pemData)
        if block == nil {
            break
        }
        log.Printf("Found a PEM block of type %s\n", block.Type)
    }
}

通过循环调用pem.Decode,可以从PEM文件中解码出所有的数据块。这对于处理包含多个证书或密钥的PEM文件特别有用。

PEM文件的加密与解密

处理加密的PEM文件通常涉及到使用密码对数据块进行加密和解密。虽然encoding/pem库本身不直接支持加密或解密操作,但它可以与其他库(如x509crypto)配合使用,来实现对PEM格式数据的加密和解密。

以下是一个使用x509crypto库加密PEM文件的例子:

这个过程通常涉及到两个主要步骤:首先,使用一个密码将私钥加密,然后将加密后的私钥保存为PEM格式;其次,从PEM格式读取加密的私钥,并使用密码进行解密。

加密私钥并保存为PEM格式

以下代码展示了如何使用x509库的EncryptPEMBlock函数加密一个RSA私钥,并将其保存为PEM格式:

package main

import (
    "crypto/rand"
    "crypto/rsa"
    "crypto/x509"
    "encoding/pem"
    "os"
)

func main() {
    // 生成RSA密钥
    privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
    if err != nil {
        panic(err)
    }

    // 定义加密密码
    password := []byte("your-encryption-password")

    // 将私钥转换为PKCS#8格式
    privBytes, err := x509.MarshalPKCS8PrivateKey(privateKey)
    if err != nil {
        panic(err)
    }

    // 加密私钥
    encBlock, err := x509.EncryptPEMBlock(rand.Reader, "ENCRYPTED PRIVATE KEY", privBytes, password, x509.PEMCipherAES256)
    if err != nil {
        panic(err)
    }

    // 保存加密的私钥到PEM文件
    file, err := os.Create("encrypted_private.pem")
    if err != nil {
        panic(err)
    }
    defer file.Close()

    if err := pem.Encode(file, encBlock); err != nil {
        panic(err)
    }
}

这段代码首先生成了一个2048位的RSA私钥,然后使用AES-256加密算法和提供的密码对其进行加密。加密后的私钥被保存在一个名为encrypted_private.pem的文件中。

从PEM格式解密私钥

解密PEM格式的加密私钥需要使用密码对其进行解密,如下所示:

package main

import (
    "crypto/x509"
    "encoding/pem"
    "io/ioutil"
    "log"
)

func main() {
    // 读取加密的PEM文件
    pemData, err := ioutil.ReadFile("encrypted_private.pem")
    if err != nil {
        log.Fatal(err)
    }

    // 解码PEM数据
    block, _ := pem.Decode(pemData)
    if block == nil || block.Type != "ENCRYPTED PRIVATE KEY" {
        log.Fatal("failed to decode PEM block containing encrypted private key")
    }

    // 解密私钥
    password := []byte("your-encryption-password")
    privBytes, err := x509.DecryptPEMBlock(block, password)
    if err != nil {
        log.Fatal(err)
    }

    // 将解密后的数据转换为私钥对象
    privateKey, err := x509.ParsePKCS8PrivateKey(privBytes)
    if err != nil {
        log.Fatal(err)
    }

    log.Printf("Private Key Type: %T\n", privateKey)
}

在这个例子中,我们首先从encrypted_private.pem文件中读取加密的PEM数据,然后使用pem.Decode函数解码出PEM块。接着,使用x509.DecryptPEMBlock函数和之前设置的密码解密私钥。最后,解密后的私钥数据被转换回rsa.PrivateKey对象,以便进一步使用。

通过这两个步骤,你可以在Go应用程序中安全地处理加密的PEM格式私钥,确保敏感信息的安全性。

在掌握了encoding/pem库的基本使用方法之后,我们现在转向一些更高级的应用场景。这些场景展示了encoding/pem库在实际开发中的强大用途,特别是在证书管理和安全通信方面。

高级应用场景

证书链的处理

在SSL/TLS通信中,证书链的正确处理对于确保通信双方的身份及数据的安全性至关重要。证书链通常包括根证书、中间证书和服务器证书。使用encoding/pem库,我们可以轻松地解析和验证证书链。

以下示例演示了如何读取和解析证书链:

package main

import (
    "crypto/x509"
    "encoding/pem"
    "io/ioutil"
    "log"
)

func main() {
    // 读取证书链文件
    certChainData, err := ioutil.ReadFile("cert_chain.pem")
    if err != nil {
        log.Fatal(err)
    }

    var certChain []*x509.Certificate
    for {
        block, rest := pem.Decode(certChainData)
        if block == nil {
            break
        }
        certChainData = rest

        if block.Type == "CERTIFICATE" {
            cert, err := x509.ParseCertificate(block.Bytes)
            if err != nil {
                log.Fatal(err)
            }
            certChain = append(certChain, cert)
        }
    }

    // 此处可以进行证书链的验证等操作
    // ...
}

这个示例首先读取了一个包含证书链的PEM文件,然后逐个解析每个证书,并将它们添加到一个证书数组中。在实际应用中,你还需要进一步验证证书链的有效性,包括证书的签名、有效期等。

生成自签名证书

自签名证书是指使用其自己的私钥进行签名的证书,通常用于测试或内部网络。使用Go语言的crypto/x509库和encoding/pem库,我们可以生成自签名证书并将其编码为PEM格式。

以下是生成自签名证书的简单示例:

package main

import (
    "crypto/ecdsa"
    "crypto/elliptic"
    "crypto/rand"
    "crypto/x509"
    "crypto/x509/pkix"
    "math/big"
    "time"
    "encoding/pem"
    "os"
)

func main() {
    // 生成ECDSA密钥对
    privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
    if err != nil {
        panic(err)
    }

    // 创建自签名证书模板
    certTemplate := x509.Certificate{
        SerialNumber: big.NewInt(1),
        Subject: pkix.Name{
            Organization: []string{"Example Co"},
        },
        NotBefore:             time.Now(),
        NotAfter:              time.Now().Add(365 * 24 * time.Hour),
        KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
        ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
        BasicConstraintsValid: true,
    }

    // 使用私钥签名证书
    certBytes, err := x509.CreateCertificate(rand.Reader, &certTemplate, &certTemplate, &privateKey.PublicKey, privateKey)
    if err != nil {
        panic(err)
    }

    // 编码证书为PEM格式
    certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certBytes})

    // 编码私钥为PEM格式
    privBytes, err := x509.MarshalECPrivateKey(privateKey)
    if err != nil {
        panic(err)
    }
    privPEM := pem.EncodeToMemory(&pem.Block{Type: "EC PRIVATE KEY", Bytes: privBytes})

    // 保存证书和私钥到文件
    ioutil.WriteFile("selfsigned_cert.pem", certPEM, 0644)
    ioutil.WriteFile("private_key.pem", privPEM, 0644)
}

这个例子首先生成了一个ECDSA密钥对,然后创建了一个自签名证书模板,最后使用私钥签名证书,并将证书和私钥分别编码为PEM格式保存到文件中。这种自签名证书适用于开发和测试环境,但不建议在生产环境中使用。

完成对encoding/pem库的高级应用场景探讨后,我们现在转向一些可能在使用这个库时遇到的常见问题及其解答。这些问题涵盖了从基本使用到高级功能的各个方面,旨在帮助开发者更有效地利用encoding/pem库。

常见问题与解答

Q1: 如何处理pem.Decode返回nil的情况?

A1:pem.Decode函数返回nil时,这通常意味着输入的PEM数据不包含有效的PEM编码块。确保输入数据正确,并且以"-----BEGIN"开头。如果数据中包含多个PEM块,你需要在循环中调用pem.Decode来依次解析每个块。

Q2: 在使用encoding/pem库处理加密PEM文件时,如何选择合适的加密算法?

A2: 选择合适的加密算法取决于你的具体需求,包括所需的安全级别和性能考虑。对于大多数应用场景,推荐使用标准的加密算法,如RSA或ECDSA。具体实现时,可以通过结合crypto/x509库来生成和管理加密密钥。

Q3: 生成的PEM文件在其他语言或工具中无法识别,原因可能是什么?

A3: 确保PEM文件的格式正确,包括PEM头部和尾部的标签匹配,并且Base64编码的数据未被破坏。不同的工具和库可能对PEM格式的容错性有不同的要求。如果可能,尝试使用标准的工具(如OpenSSL)验证PEM文件的有效性。

Q4: 如何将PEM文件转换为其他格式,如DER?

A4: PEM到DER的转换涉及去除PEM的头部和尾部标签,并对剩余的Base64编码的内容进行解码。可以使用encoding/pem库读取PEM文件,然后使用base64.StdEncoding.DecodeString函数直接对内容进行解码。转换后的DER格式可以用于那些要求二进制格式的场景。

Q5: 在处理大量的PEM文件时,有没有性能优化的建议?

A5: 处理大量PEM文件时,考虑并行处理各个文件,特别是当涉及到密钥生成或加密解密操作时。Go语言的并发模型(goroutines和channels)为此提供了强大的支持。同时,确保合理管理内存使用,避免在处理大型文件时造成内存溢出。

结语

通过本文,我们全面介绍了Go语言的encoding/pem库,从基础用法到高级应用,再到常见问题的解答。encoding/pem库是处理PEM格式数据的强大工具,无论是在开发安全相关的应用,还是在进行证书和密钥管理时,都能发挥重要作用。希望本文能帮助你更好地理解和使用这个库,提高你的开发效率和应用的安全性。

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

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

相关文章

代码随想录训练营Day25:● 216.组合总和III ● 17.电话号码的字母组合

216.组合总和III 题目链接 https://leetcode.cn/problems/combination-sum-iii/description/ 题目描述 思路 自己写的效率会慢一些&#xff0c;而且没有用到剪枝 class Solution {List<List<Integer>> list new ArrayList<>();List<Integer> lis…

基于PIESDK的二次开发--土壤水反演系统

目录 系统演示数据获取算法封装系统 系统演示 数据获取 基于TVDI的土壤水分反演需要有地表温度和植被指数数据&#xff0c;该部分参考Landsat计算TVDI进行干旱监测&#xff08;二&#xff09; 得到两张TIF影像 算法封装 初始的.py代码参数是直接指定的&#xff0c;然而在封…

【Javascript编程实操06】1、反转数组和字符串 2、将二维数组转一维数组

前言 1、反转数组和字符串 代码&#xff1a; 实现效果&#xff1a; 2、将二维数组转一维数组 代码&#xff1a; 实现效果&#xff1a; 总结 前言 本次主要是针对Javascript阶段的字符串与数组的实操练习&#xff0c;共有2个实操&#xff0c;大家可以在实操的过程中更加深…

ARM 寄存器学习:(一)arm多种模式下得寄存器

一.ARM7种状态以及每种状态的寄存器&#xff1a; ARM 处理器共有 7 种不同的处理器模式&#xff0c;在每一种处理器模式中可见的寄存器包括 15 个通用寄存器( R0~R14)、一个或两个(User和Sys不是异常模式&#xff0c;没有spsr寄存器)状态寄存器&#xff08;cpsr和spsr&…

想兼职赚钱?盘点6个靠谱兼职,赚钱更轻松!

1&#xff0c;微头条搬砖 微头条搬砖是一个门槛不高的赚钱方式&#xff0c;而且不需要你有多么好的原创能力&#xff0c;去收集一些热门文章的素材进行文章伪原创&#xff0c;十分钟就能搞定&#xff0c;只要你的文章有爆点&#xff0c;足够吸人眼球&#xff0c;就能够获取不低…

Web核心,HTTP,tomcat,Servlet

1&#xff0c;JavaWeb技术栈 B/S架构:Browser/Server&#xff0c;浏览器/服务器架构模式&#xff0c;它的特点是&#xff0c;客户端只需要浏览器&#xff0c;应用程序的逻辑和数据都存储在服务器端。浏览器只需要请求服务器&#xff0c;获取Web资源&#xff0c;服务器把Web资源…

Linux服务器(Debian系)包含UOS安全相关巡检shell脚本

#!/bin/bash# Define output file current_date$(date "%Y%m%d") # Gets the current date in YYYYMMDD format output_file"server_security_inspection_report_${current_date}.txt"# Empty the file initially echo > $output_file# 获取巡检时间 (…

蓝桥杯刷题(九)

1.三国游戏 代码 #输入数据 nint(input()) Xlilist(map(int,input().split())) Ylilist(map(int,input().split())) Zlilist(map(int,input().split())) #分别计算X-Y-Z/Y-Z-X/Z-X-Y并排序 newXli sorted([Xli[i] - Yli[i] - Zli[i] for i in range(n)],reverseTrue) newYli …

Pikachu 靶场搭建

文章目录 环境说明1 Pikachu 简介2 Pikachu 安装 环境说明 操作系统&#xff1a;Windows 10PHPStudy 版本: 8.1.1.3Apache 版本&#xff1a;2.4.39MySQL 版本 5.7.26 1 Pikachu 简介 Pikachu是一个使用“PHP MySQL” 开发、包含常见的Web安全漏洞、适合Web渗透测试学习人员练…

腾讯云轻量2核4G5M服务器卡不卡?性能怎么样?

腾讯云轻量2核4G5M带宽服务器支持多少人在线访问&#xff1f;5M带宽下载速度峰值可达640KB/秒&#xff0c;阿腾云以搭建网站为例&#xff0c;假设优化后平均大小为60KB&#xff0c;则5M带宽可支撑10个用户同时在1秒内打开网站&#xff0c;并发数为10&#xff0c;经阿腾云测试&a…

C++算法学习心得八.动态规划算法(4)

1.零钱兑换&#xff08;322题&#xff09; 题目描述&#xff1a; 给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额&#xff0c;返回 -1。 你可以认为每种硬币的数量是无限的。…

劲仔食品三年倍增,抢先打响鹌鹑蛋“健康”属性品牌之争?

如果说&#xff0c;进入2024年后&#xff0c;在股价继续陷入回调状态的食品板块中有个股走势表现相对亮眼&#xff0c;那么劲仔食品必是其中之一。 从去年发布2023年三季度业绩公告以来&#xff0c;其强劲的业绩表现就带动了股价走出小趋势。2023年10月23日至今2024年3月13日收…

VTK安装(C++)并配置vs

准备工作&#xff1a; 1.VTK下载包(此教程使用VTK8.2.0) 2.CMAKE(此教程使用3.29.0) 在此不过多赘述&#xff0c;可在网上搜索cmake安装 3.visual studio(此教程使用vs2019) VTK下载及编译&#xff1a; 1、找到自己适合的VTK版本,我选择的是VTK8.2.0。 1.1 官网下载&#xff…

向量相似性度量的常用方法

向量相似性度量的常用方法 0. 引言1. 欧氏距离(Euclidean distance)2. 余弦相似度(Cosine similarity)3. 汉明距离(Hamming distance)4. 点积相似度 (Dot Product Similarity)5. 曼哈顿距离 (Manhattan Distance) 0. 引言 今天花时间学习学习向量相似性度量的常用方法&#xf…

c语言按位与,按位或,按位异或,按位取反

1、按位与& 按位与的实现逻辑是相同为1&#xff0c;相异为0&#xff1b; 2、按位或 | 按位或的实现逻辑是有1为1&#xff0c;无一为0&#xff1b; 3、按位异或 ^ 按位或的实现逻辑是相同为0&#xff0c;相异为1&#xff1b; 4、按位取反 ~ 按位取反的实现逻辑是0改1&am…

Postman-Installation has failed

如图&#xff1a; 解决方法&#xff1a; 打开文件夹 Postman-win64-Setup 点击Postman.exe 即可

Nginx高级技术: 代理缓存配置

一、缓存说明 Nginx缓存&#xff0c;Nginx 提供了一个强大的反向代理和 HTTP 服务器功能&#xff0c;同时也是一个高效的缓存服务器。一般情况下系统用到的缓存有以下三种&#xff1a; 1、服务端缓存&#xff1a;缓存存在后端服务器&#xff0c;如 redis。 2、代理缓存&#…

L1-5 试试手气 【Java】

我们知道一个骰子有 6 个面&#xff0c;分别刻了 1 到 6 个点。下面给你 6 个骰子的初始状态&#xff0c;即它们朝上一面的点数&#xff0c;让你一把抓起摇出另一套结果。假设你摇骰子的手段特别精妙&#xff0c;每次摇出的结果都满足以下两个条件&#xff1a; 1、每个骰子摇出…

llamma笔记:部署Llama2

1 申请Llama2 许可 Download Llama (meta.com) 地址似乎不能填中国 1.1 获取url 提交申请后&#xff0c;填的那个邮箱会受到一封meta发来的邮件&#xff0c;打码部分的url&#xff0c;之后会用得上 2 ubuntu/linux 端部署Llama2 2.1 git clone Llama2的github 仓库 bash g…

腾讯云2核4g服务器能多少人在线?2核4G云服务器支持多少并发?

腾讯云轻量2核4G5M带宽服务器支持多少人在线访问&#xff1f;5M带宽下载速度峰值可达640KB/秒&#xff0c;阿腾云以搭建网站为例&#xff0c;假设优化后平均大小为60KB&#xff0c;则5M带宽可支撑10个用户同时在1秒内打开网站&#xff0c;并发数为10&#xff0c;经阿腾云测试&a…