fix(crypto): 扩展确定性密钥字节流(by AI)
This commit is contained in:
parent
ac258d4f64
commit
5c497ba57b
@ -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`。
|
||||
|
||||
|
||||
3
TEST.md
3
TEST.md
@ -1,5 +1,8 @@
|
||||
# Test Report: @go/crypto
|
||||
|
||||
## v1.5.5 验证
|
||||
- 全量测试与基准测试通过;密码派生非对称密钥回归连续运行 10 次通过。
|
||||
|
||||
## 📋 测试概览
|
||||
- **测试时间**: 2026-06-21
|
||||
- **测试环境**: darwin/amd64
|
||||
|
||||
2
go.mod
2
go.mod
@ -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
22
go.sum
@ -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=
|
||||
|
||||
43
password.go
43
password.go
@ -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
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user