Skip to content

Commit

Permalink
添加更多pbkdf
Browse files Browse the repository at this point in the history
  • Loading branch information
deatil committed Oct 8, 2024
1 parent be9f019 commit 7c03223
Show file tree
Hide file tree
Showing 5 changed files with 331 additions and 3 deletions.
6 changes: 3 additions & 3 deletions elliptic/bign/curve/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ var curves = []struct {
BuildTags string
}{
{
P: "P256",
Element: "fiat.P256Element",
Params: &elliptic.CurveParams{
P: "P256",
Element: "fiat.P256Element",
Params: &elliptic.CurveParams{
Name: "BIGN256V1",
BitSize: 256,
P: bigFromHex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff43"),
Expand Down
59 changes: 59 additions & 0 deletions kdf/pgp_s2k/iters.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package pgp_s2k

var s2kIters = [256]uint32{
1024, 1088, 1152, 1216, 1280, 1344, 1408, 1472, 1536, 1600, 1664,
1728, 1792, 1856, 1920, 1984, 2048, 2176, 2304, 2432, 2560, 2688,
2816, 2944, 3072, 3200, 3328, 3456, 3584, 3712, 3840, 3968, 4096,
4352, 4608, 4864, 5120, 5376, 5632, 5888, 6144, 6400, 6656, 6912,
7168, 7424, 7680, 7936, 8192, 8704, 9216, 9728, 10240, 10752, 11264,
11776, 12288, 12800, 13312, 13824, 14336, 14848, 15360, 15872, 16384, 17408,
18432, 19456, 20480, 21504, 22528, 23552, 24576, 25600, 26624, 27648, 28672,
29696, 30720, 31744, 32768, 34816, 36864, 38912, 40960, 43008, 45056, 47104,
49152, 51200, 53248, 55296, 57344, 59392, 61440, 63488, 65536, 69632, 73728,
77824, 81920, 86016, 90112, 94208, 98304, 102400, 106496, 110592, 114688, 118784,
122880, 126976, 131072, 139264, 147456, 155648, 163840, 172032, 180224, 188416, 196608,
204800, 212992, 221184, 229376, 237568, 245760, 253952, 262144, 278528, 294912, 311296,
327680, 344064, 360448, 376832, 393216, 409600, 425984, 442368, 458752, 475136, 491520,
507904, 524288, 557056, 589824, 622592, 655360, 688128, 720896, 753664, 786432, 819200,
851968, 884736, 917504, 950272, 983040, 1015808, 1048576, 1114112, 1179648, 1245184, 1310720,
1376256, 1441792, 1507328, 1572864, 1638400, 1703936, 1769472, 1835008, 1900544, 1966080, 2031616,
2097152, 2228224, 2359296, 2490368, 2621440, 2752512, 2883584, 3014656, 3145728, 3276800, 3407872,
3538944, 3670016, 3801088, 3932160, 4063232, 4194304, 4456448, 4718592, 4980736, 5242880, 5505024,
5767168, 6029312, 6291456, 6553600, 6815744, 7077888, 7340032, 7602176, 7864320, 8126464, 8388608,
8912896, 9437184, 9961472, 10485760, 11010048, 11534336, 12058624, 12582912, 13107200, 13631488, 14155776,
14680064, 15204352, 15728640, 16252928, 16777216, 17825792, 18874368, 19922944, 20971520, 22020096, 23068672,
24117248, 25165824, 26214400, 27262976, 28311552, 29360128, 30408704, 31457280, 32505856, 33554432, 35651584,
37748736, 39845888, 41943040, 44040192, 46137344, 48234496, 50331648, 52428800, 54525952, 56623104, 58720256,
60817408, 62914560, 65011712};

func encodeCount(desiredIterations uint32) uint8 {
if desiredIterations <= s2kIters[0] {
return 0
}

if desiredIterations >= s2kIters[255] {
return 255
}

i := lowerBound(s2kIters[:], desiredIterations)

return uint8(i)
}

func decodeCount(iter uint8) uint32 {
return s2kIters[iter]
}

func roundIterations(iterations uint32) uint32 {
return decodeCount(encodeCount(iterations))
}

func lowerBound(s2kIters []uint32, iter uint32) int {
for k, v := range s2kIters {
if v >= iter {
return k
}
}

return len(s2kIters)
}
92 changes: 92 additions & 0 deletions kdf/pgp_s2k/pgp_s2k.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package pgp_s2k

import (
"time"
"hash"
"bytes"
)

/**
* OpenPGP's S2K
*
* See RFC 4880 sections 3.7.1.1, 3.7.1.2, and 3.7.1.3
* If the salt is empty and iterations == 1, "simple" S2K is used
* If the salt is non-empty and iterations == 1, "salted" S2K is used
* If the salt is non-empty and iterations > 1, "iterated" S2K is used
*
* Due to complexities of the PGP S2K algorithm, time-based derivation
* is not supported. So if iterations == 0 and msec.count() > 0, an
* exception is thrown. In the future this may be supported, in which
* case "iterated" S2K will be used and the number of iterations
* performed is returned.
*/
func Key(h func() hash.Hash, password, salt []byte, iterations, keylen int) []byte {
if (iterations > 1 && len(salt) == 0) {
panic("go-cryptobin/pgp_s2k: OpenPGP S2K requires a salt in iterated mode")
}

newHash := h()

inputBuf := make([]byte, len(salt) + len(password))
copy(inputBuf[:], salt)
copy(inputBuf[len(salt):], password)

var hashBuf []byte
var outputBuf []byte

var pass int = 0
var generated int = 0

for generated < keylen {
output_this_pass := mathMin(newHash.Size(), keylen - generated)

newHash.Reset()

// Preload some number of zero bytes (empty first iteration)
zero_padding := bytes.Repeat([]byte{0}, pass)
newHash.Write(zero_padding)

// The input is always fully processed even if iterations is very small
if len(inputBuf) > 0 {
left := mathMax(iterations, len(inputBuf))
for left > 0 {
input_to_take := mathMin(left, len(inputBuf))
newHash.Write(inputBuf[:input_to_take])
left -= input_to_take
}
}

hashBuf = newHash.Sum(nil)

outputBuf = append(outputBuf, hashBuf[:output_this_pass]...)

generated += output_this_pass
pass++
}

return outputBuf
}

func KeyWithTune(h func() hash.Hash, password, salt []byte, iterations, keylen int, msec time.Duration) []byte {
if iterations == 0 {
iterations = tune(h(), keylen, msec, 0, 10 * time.Millisecond)
}

return Key(h, password, salt, iterations, keylen)
}

func mathMin(a, b int) int {
if a < b {
return a
}

return b
}

func mathMax(a, b int) int {
if a > b {
return a
}

return b
}
124 changes: 124 additions & 0 deletions kdf/pgp_s2k/pgp_s2k_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package pgp_s2k

import (
"hash"
"bytes"
"testing"
"crypto/sha1"
"crypto/sha512"
"encoding/hex"
)

func fromHex(s string) []byte {
h, _ := hex.DecodeString(s)
return h
}

type testVector struct {
password string
salt []byte
iter int
output []byte
}

var sha1TestVectors = []testVector{
{
"",
fromHex(""),
1,
fromHex("DA39A3EE5E6B"),
},
{
"hello",
fromHex(""),
1,
fromHex("AAF4C61D"),
},
{
"hello",
fromHex("01020304"),
1,
fromHex("10295AC1"),
},
{
"bar",
fromHex("01020304"),
1,
fromHex("BD8AAC6B9EA9CAE04EAE6A91C6133B58B5D9A61C14F355516ED9370456"),
},
{
"bar",
fromHex("04030201"),
31,
fromHex("2AF5A99B54F093789FD657F19BD245AF7604D0F6AE06F66602A46A08AE"),
},
{
"ilikepie",
fromHex("2AE6E5831A717917"),
65536,
fromHex("A32F874A4CF95DFAD8359302B395455C"),
},
{
"passphrase",
fromHex("0102030405060708"),
1,
fromHex("eec8929a31187dd3a9a7ce5a97d96a67706382bbef70fe3b2a3aeeaf176bce252c117970a51fd8b770a69f8ecb199505395bd7b0c0760d6a38ac82900b23fe3b"),
},
{
"passphrase",
fromHex("0102030405060708"),
65536,
fromHex("24ce08a4a31de2208acdc15347def7a63492d38a0c08f80533a746279d91cb25e1b6b740b09e20a4884ca1944d506eb200753761066e8d4b24957c2593388457"),
},
{
"passphrase",
fromHex("0102030405060708"),
10000000,
fromHex("09efbd3599e2453c6cf1749a7ed169514a12d1a721549468c6d0ef6737fa3e27ab6d100f9839694fc70c484a42b00ef87463d07e2aafb92033843a4bd5f37971"),
},
}

var sha384TestVectors = []testVector{
{
"passphrase",
fromHex("0102030405060708"),
1,
fromHex("ea024c2de8af9a3edfbac9422f7b17e17c3165147b43f4edd58b55af9a412d07e0631f431a7e0028fbb145d9d5e059a888f1a7526cd338b1b6082a8681b446fa"),
},
{
"passphrase",
fromHex("0102030405060708"),
18,
fromHex("ea024c2de8af9a3edfbac9422f7b17e17c3165147b43f4edd58b55af9a412d07e0631f431a7e0028fbb145d9d5e059a888f1a7526cd338b1b6082a8681b446fa"),
},
{
"passphrase",
fromHex("0102030405060708"),
19,
fromHex("491aa377a1a9526d53b118587a03f85f5dc64568f3aabaad66aafc923397fb74d7017a6a4812bff2d9beddcbc6a0dbd3b96a3f9a69b637d68670acd48d4dfa4e"),
},
{
"passphrase",
fromHex("0102030405060708"),
1000000,
fromHex("af4986488f4e53ac4f7991a0bb8de15441ba1070481fe63b126ff3de2e1072f568dd3d6c5887d008925d27649494ae6f4860e141d5eeabe4f93745ca9cb8e08c"),
},

}

func testHash(t *testing.T, h func() hash.Hash, hashName string, vectors []testVector) {
for i, v := range vectors {
o := Key(h, []byte(v.password), v.salt, v.iter, len(v.output))
if !bytes.Equal(o, v.output) {
t.Errorf("%s %d: want %x, got %x", hashName, i, v.output, o)
}
}
}

func TestWithSHA1(t *testing.T) {
testHash(t, sha1.New, "SHA1", sha1TestVectors)
}

func TestWithSHA384(t *testing.T) {
testHash(t, sha512.New384, "SHA384", sha384TestVectors)
}
53 changes: 53 additions & 0 deletions kdf/pgp_s2k/s2k_family.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package pgp_s2k

import (
"time"
"hash"
)

func tune(h hash.Hash, keylen int, msec time.Duration, _ int, tune_time time.Duration) int {
var buf_size int = 1024
var buffer = make([]byte, buf_size)
var time_used uint64 = 0
var event_count uint64 = 0

td := time.Duration(buf_size)

timer := time.NewTimer(td)
for {
select {
case <-timer.C:
event_count++
time_used = time_used + uint64(td)

h.Write(buffer)

if time.Duration(time_used) < tune_time {
timer.Reset(td)
}
}
}

var hash_bytes_per_second uint64
if td.Seconds() > 0 {
hash_bytes_per_second = (uint64(buf_size) * event_count) / uint64(td.Seconds())
} else {
hash_bytes_per_second = 0
}

desired_nsec := uint64(msec.Nanoseconds())

hash_size := h.Size()

var blocks_required int
if keylen <= hash_size {
blocks_required = 1
} else {
blocks_required = (keylen + hash_size - 1) / hash_size
}

bytes_to_be_hashed := (hash_bytes_per_second * (desired_nsec / 1000000000)) / uint64(blocks_required)
iterations := roundIterations(uint32(bytes_to_be_hashed))

return int(iterations)
}

0 comments on commit 7c03223

Please sign in to comment.