fix(crypto): 扩展确定性密钥字节流(by AI)

This commit is contained in:
Star 2026-07-18 19:00:27 +08:00
parent ac258d4f64
commit 5c497ba57b
5 changed files with 62 additions and 12 deletions

View File

@ -1,5 +1,9 @@
# Changelog: @go/crypto
## v1.5.5 (2026-07-18)
- **确定性密钥修复**: HKDF 首轮耗尽后使用带轮次域分离的新一轮字节流,避免 RSA 密钥生成触发 entropy limit同时保留原有首轮输出。
- **依赖校验修复**: 重新整理模块图并补齐 checksum。
## v1.5.4 (2026-06-21)
- **命名规范**: SHA 缩写全大写,`Sha1`/`Sha256`/`Sha512``SHA1`/`SHA256`/`SHA512`HMAC 系列同步修正为 `HMACSHA1`/`HMACSHA256`/`HMACSHA512`

View File

@ -1,5 +1,8 @@
# Test Report: @go/crypto
## v1.5.5 验证
- 全量测试与基准测试通过;密码派生非对称密钥回归连续运行 10 次通过。
## 📋 测试概览
- **测试时间**: 2026-06-21
- **测试环境**: darwin/amd64

2
go.mod
View File

@ -11,6 +11,6 @@ require (
)
require (
apigo.cc/go/rand v1.5.3
apigo.cc/go/rand v1.5.3 // indirect
golang.org/x/sys v0.45.0 // indirect
)

22
go.sum
View File

@ -1,12 +1,14 @@
apigo.cc/go/cast v1.5.0 h1:UBGJtFQ8eJPMQXs37cUgqd7YQo1zI9opuSDBDmn2/pE=
apigo.cc/go/cast v1.5.0/go.mod h1:z2GW5p5WCZGEqVVIJUdhl232vRbLf2Qu4EDlEakX/D8=
apigo.cc/go/encoding v1.5.0 h1:EJNdRVDOMoI2DAvZwQNQTbYuqB/6zsEzvg7lS5pQI+I=
apigo.cc/go/encoding v1.5.0/go.mod h1:8++NfZj3hWig0qh2g7GQRw/4LpSvCYMWUZ+8J+x58cA=
apigo.cc/go/jsmod v1.5.0 h1:JgQtJNiJWy1NOP9AzE8NX5VXJkpO/x3GqLsCCSny5Ec=
apigo.cc/go/jsmod v1.5.0/go.mod h1:bmyeZtOAP/j5am+YRnaiM89smysK24K7ebk0koFtsSw=
apigo.cc/go/rand v1.5.0 h1:1o8hh8fhdBuk1/h02IvugvamuT3dkWbVJrqEJVQKB2E=
apigo.cc/go/rand v1.5.0/go.mod h1:Lh98S2dm9UY0X+M+kNQQEKyXHG5pcCKSFPyXN0QCGdk=
apigo.cc/go/safe v1.5.0 h1:W1NblmcU8cex1f9Y5z8mNLUJOzZTE1s6fszb3FbhGnk=
apigo.cc/go/safe v1.5.0/go.mod h1:OfQ5d6COePSGEuPvMeOk6KagX2sezw7nvKh7exj9SeM=
apigo.cc/go/cast v1.5.3 h1:jk6VX0rGFhjKtfPhsaV6IKYpiGmORRk9qPTtuNS53tw=
apigo.cc/go/cast v1.5.3/go.mod h1:GMjjrYn93tWat1U409G7h1jR3ejfLLI7r0efBo9Sbd4=
apigo.cc/go/encoding v1.5.4 h1:Fk8TrveZATyy8SHukC4ZiqdTSp+QIfsRHtt55xmMK7w=
apigo.cc/go/encoding v1.5.4/go.mod h1:dShEsZ3gKqBINz7TSOYf4e7/fBCqCY9VzlenoGUQUFM=
apigo.cc/go/jsmod v1.5.3 h1:S3W317bH0QV2NMeRO1E0v6ySIBOfMWYv/NuQJbvqKWU=
apigo.cc/go/jsmod v1.5.3/go.mod h1:bmyeZtOAP/j5am+YRnaiM89smysK24K7ebk0koFtsSw=
apigo.cc/go/rand v1.5.3 h1:O4bPIwyaOWEBCr0nL9A4G4qG48AqiGTCzfPeckm3Ius=
apigo.cc/go/rand v1.5.3/go.mod h1:q1BTFkY/cXE229dDD5Q22lF7T0DoKPV6xAu+6bCrDH4=
apigo.cc/go/safe v1.5.2 h1:EnuEOW/SGwf/5A0nw9LnqfKJE071+TIc6ez8HI9R9Lg=
apigo.cc/go/safe v1.5.2/go.mod h1:2GqCCLLGex4OAhdET3iBWm1R+LIYtmTrvHP8W0iESSw=
golang.org/x/crypto v0.52.0 h1:RMs7fP2rXdep0CftQlK8Uf+kibLm7qkCcradZWYz988=
golang.org/x/crypto v0.52.0/go.mod h1:1QgfPxDqh0T2M/elOJtp9RvuR95kVjir0e6/BvEmGbc=
golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY=
golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=

View File

@ -2,6 +2,7 @@ package crypto
import (
"crypto/sha256"
"encoding/binary"
"io"
"apigo.cc/go/safe"
@ -26,5 +27,45 @@ func DeriveKey(password, salt []byte, keyLen uint32) []byte {
// NewDeterministicReader creates an io.Reader that produces a deterministic stream of bytes from a seed.
// This is used to make RSA/ECDSA key generation deterministic based on a password.
func NewDeterministicReader(seed []byte, info []byte) io.Reader {
return hkdf.New(sha256.New, seed, nil, info)
return newExpandingHKDFReader(seed, info)
}
type expandingHKDFReader struct {
seed []byte
info []byte
round uint64
current io.Reader
}
func newExpandingHKDFReader(seed, info []byte) io.Reader {
r := &expandingHKDFReader{
seed: append([]byte(nil), seed...),
info: append([]byte(nil), info...),
}
r.reset()
return r
}
func (r *expandingHKDFReader) reset() {
info := r.info
if r.round > 0 {
info = make([]byte, len(r.info)+8)
copy(info, r.info)
binary.BigEndian.PutUint64(info[len(r.info):], r.round)
}
r.current = hkdf.New(sha256.New, r.seed, nil, info)
r.round++
}
func (r *expandingHKDFReader) Read(p []byte) (int, error) {
total := 0
for total < len(p) {
n, err := r.current.Read(p[total:])
total += n
if err == nil {
continue
}
r.reset()
}
return total, nil
}