forked from go-chef/chef
/
authentication.go
122 lines (107 loc) · 2.74 KB
/
authentication.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package chef
import (
"crypto/rsa"
"crypto/sha1"
"encoding/base64"
"errors"
"io"
"math/big"
)
// GenerateSignature will generate a signature ( sign ) the given data
func GenerateSignature(priv *rsa.PrivateKey, data string) (enc []byte, err error) {
sig, err := privateEncrypt(priv, []byte(data))
if err != nil {
return nil, err
}
return sig, nil
}
// privateEncrypt implements OpenSSL's RSA_private_encrypt function
func privateEncrypt(key *rsa.PrivateKey, data []byte) (enc []byte, err error) {
k := (key.N.BitLen() + 7) / 8
tLen := len(data)
// rfc2313, section 8:
// The length of the data D shall not be more than k-11 octets
if tLen > k-11 {
err = errors.New("Data too long")
return
}
em := make([]byte, k)
em[1] = 1
for i := 2; i < k-tLen-1; i++ {
em[i] = 0xff
}
copy(em[k-tLen:k], data)
c := new(big.Int).SetBytes(em)
if c.Cmp(key.N) > 0 {
err = nil
return
}
var m *big.Int
var ir *big.Int
if key.Precomputed.Dp == nil {
m = new(big.Int).Exp(c, key.D, key.N)
} else {
// We have the precalculated values needed for the CRT.
m = new(big.Int).Exp(c, key.Precomputed.Dp, key.Primes[0])
m2 := new(big.Int).Exp(c, key.Precomputed.Dq, key.Primes[1])
m.Sub(m, m2)
if m.Sign() < 0 {
m.Add(m, key.Primes[0])
}
m.Mul(m, key.Precomputed.Qinv)
m.Mod(m, key.Primes[0])
m.Mul(m, key.Primes[1])
m.Add(m, m2)
for i, values := range key.Precomputed.CRTValues {
prime := key.Primes[2+i]
m2.Exp(c, values.Exp, prime)
m2.Sub(m2, m)
m2.Mul(m2, values.Coeff)
m2.Mod(m2, prime)
if m2.Sign() < 0 {
m2.Add(m2, prime)
}
m2.Mul(m2, values.R)
m.Add(m, m2)
}
}
if ir != nil {
// Unblind.
m.Mul(m, ir)
m.Mod(m, key.N)
}
enc = m.Bytes()
return
}
// HashStr returns the base64 encoded SHA1 sum of the toHash string
func HashStr(toHash string) string {
h := sha1.New()
io.WriteString(h, toHash)
hashed := base64.StdEncoding.EncodeToString(h.Sum(nil))
return hashed
}
// Base64BlockEncode takes a byte slice and breaks it up into a
// slice of base64 encoded strings
func Base64BlockEncode(content []byte, limit int) []string {
resultString := base64.StdEncoding.EncodeToString(content)
var resultSlice []string
index := 0
var maxLengthPerSlice int
// No limit
if limit == 0 {
maxLengthPerSlice = len(resultString)
} else {
maxLengthPerSlice = limit
}
// Iterate through the encoded string storing
// a max of <limit> per slice item
for i := 0; i < len(resultString)/maxLengthPerSlice; i++ {
resultSlice = append(resultSlice, resultString[index:index+maxLengthPerSlice])
index += maxLengthPerSlice
}
// Add remaining chunk to the end of the slice
if len(resultString)%maxLengthPerSlice != 0 {
resultSlice = append(resultSlice, resultString[index:])
}
return resultSlice
}