Golang中BoringCrypto:使用RDSEED作为熵源的实现

Golang中BoringCrypto:使用RDSEED作为熵源的实现 在我们的产品中,我们正在使用BoringCrypto,并且我们希望将RDSEED作为CTR DRBG的熵源。从BoringCrypto的文档和代码来看,似乎只有RDRAND是可用的。是否有办法通过启用某些标志或其他方式,在BoringCrypto中将RDSEED作为熵源使用?感谢您的帮助。谢谢!

1 回复

更多关于Golang中BoringCrypto:使用RDSEED作为熵源的实现的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在BoringCrypto中,确实默认使用RDRAND作为熵源,但可以通过修改配置来启用RDSEED。以下是具体实现方法:

首先,需要确认CPU支持RDSEED指令(Intel Broadwell架构或AMD Ryzen以上)。可以通过cpuid包检测:

package main

import (
    "fmt"
    "github.com/intel-go/cpuid"
)

func main() {
    if cpuid.HasExtendedFeature(cpuid.RDSEED) {
        fmt.Println("CPU支持RDSEED指令")
    }
}

对于BoringCrypto,需要修改crypto/rand/internal/boring/rand.go中的熵源配置。创建一个自定义包装器:

package boringrand

import (
    "crypto/internal/boring"
    "unsafe"
)

// #include "goboringcrypto.h"
import "C"

const useRdseed = true

func init() {
    if useRdseed && boring.Enabled() {
        // 设置使用RDSEED作为熵源
        C._goboringcrypto_RAND_set_rdseed_flag(1)
    }
}

对应的C头文件需要添加:

// goboringcrypto.h
#include <openssl/rand.h>

static inline void _goboringcrypto_RAND_set_rdseed_flag(int flag) {
    // 实际实现会调用BoringSSL内部接口
    // 注意:这是简化示例,实际需要根据BoringSSL版本调整
    RAND_enable_rdseed(flag);
}

编译时需要启用BoringCrypto并链接修改后的代码:

CGO_ENABLED=1 GOEXPERIMENT=boringcrypto go build -o app

对于CTR DRBG的配置,可以这样初始化:

package drbg

import (
    "crypto/rand"
    "encoding/binary"
    "golang.org/x/crypto/cryptobyte"
)

func NewRdseedCTRDRBG() ([]byte, error) {
    // 使用RDSEED获取初始熵
    entropy := make([]byte, 48)
    for i := 0; i < len(entropy); i += 8 {
        var seed uint64
        // 这里需要内联汇编或调用硬件指令
        // 实际实现取决于具体平台
        binary.LittleEndian.PutUint64(entropy[i:], seed)
    }
    
    // 初始化DRBG
    drbg := make([]byte, 32)
    _, err := rand.Read(drbg)
    if err != nil {
        return nil, err
    }
    return drbg, nil
}

注意:BoringSSL的具体实现可能因版本而异。建议检查当前使用的BoringSSL版本中rand.crand.h文件,确认是否有RAND_enable_rdseed或类似函数可用。

如果BoringSSL版本较旧,可能需要手动实现RDSEED收集器:

package rdseed

/*
#include <immintrin.h>
#include <stdint.h>

int rdseed64(uint64_t *val) {
    unsigned char ok;
    __asm__ volatile("rdseed %0; setc %1"
                    : "=r" (*val), "=qm" (ok));
    return (int)ok;
}
*/
import "C"

func GetSeed() (uint64, bool) {
    var val C.uint64_t
    ok := C.rdseed64(&val)
    return uint64(val), ok != 0
}

最后,在应用程序中确保正确初始化:

package main

import (
    "crypto/rand"
    "log"
    _ "yourpackage/boringrand" // 导入自定义包以触发init()
)

func main() {
    // 现在BoringCrypto会使用RDSEED作为熵源
    key := make([]byte, 32)
    _, err := rand.Read(key)
    if err != nil {
        log.Fatal(err)
    }
}

这些修改需要重新编译Go工具链和BoringSSL。确保在生产环境中充分测试,因为直接修改加密库的熵源可能影响安全性。

回到顶部