Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 1 addition & 65 deletions authentication.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ import (
"crypto/sha1"
"crypto/sha256"
"encoding/base64"
"errors"
"io"
"math/big"
)

// GenerateDigestSignature will generate a signature of the given data protocol 1.3
Expand All @@ -24,76 +22,14 @@ func GenerateDigestSignature(priv *rsa.PrivateKey, string_to_sign string) (sig [

// 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))
sig, err := rsa.SignPKCS1v15(rand.Reader, priv, 0, []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()
Expand Down
84 changes: 70 additions & 14 deletions authentication_test.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
package chef

import (
"crypto/rsa"
"encoding/base64"
"testing"

"github.com/stretchr/testify/assert"
)

type privateKey struct {
name string
key *rsa.PrivateKey
}

const (
teststr = "Hash this string"
testsha1 = "hdBcDGYOo5/Q4k2DojVVP1ANs3U="
testsha256 = "HKxj85/WjYxTHye4B2EPs9UPD8PxhplXZ/tjFucgCj4="
signature10 = "Z6mh9AcCOylVV4mR2MdgQ+FxriOjFipbcowQkDNIOT9o2pVxdzqC4mstZfF430wAEd+HLPXldJafQINmWpHzG2tDd+ms3WQBIq2/kCLmSljP7DHulOsJVeznXtcOwlg6KP4xTK4CYZoh8YuqW3VbdXyGwgx8iOKYac7EBFoKHxu2B4ggDq6NhDvYTA7eNLdXhaotEh6oNkiTByWndUki0boz82R6jMBtMw0ww4ENhZ6Mt3KeC95cFpv5dhmLXWGYVCbCnhWHsUuQlW5Ii1897muSWa+nlQBK6EBiqL8GD/3X8hHta9YLt8zM7W0hqo4NmFKie6mCaaX51Z6ExzUEgw=="
signature13 = "EuuCVnnbDBah5WiTy9cM1OwhPp+rEQl6L60E9dpYCEcvCMdvs5G6fVuW9wyo7wHlLETMmbltNccdmlByACWKobFi98oH/aYTz6Z7qRxiAJX8Z/b6C6K1c5mxKeJguOt86SGKd6aqQ4O20bXncKJ6u9HxfALphYHIJHegXC414bGbnWbDowI9ZQpNWZ/10bqyoOIiGAOJbzmU2jn6+2eey78sTbKYmddNJzaVzJAq7dtHvGG0yE1h0Y3lCN3mWP9rVu2tVClXKhpOJ1CQGY7t3gVrBtVVvgdQNBW5rhGWDD6BkwRigGiwBczSVk8a1oTiAMRHPXurrEr+c7ArItrUvA=="
privateKeyG = `
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAx12nDxxOwSPHRSJEDz67a0folBqElzlu2oGMiUTS+dqtj3FU
Expand Down Expand Up @@ -36,32 +47,77 @@ rlXw1QKBgQDBOyUJKQOgDE2u9EHybhCIbfowyIE22qn9a3WjQgfxFJ+aAL9Bg124
fJIEzz43fJ91fe5lTOgyMF5TtU5ClAOPGtlWnXU0e5j3L4LjbcqzEbeyxvP3sn1z
dYkX7NdNQ5E6tcJZuJCGq0HxIAQeKPf3x9DRKzMnLply6BEzyuAC4g==
-----END RSA PRIVATE KEY-----
`
privateKey8 = `
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDHXacPHE7BI8dF
IkQPPrtrR+iUGoSXOW7agYyJRNL52q2PcVSHmUlzUyNymtFXFwNXCGxJKj33jxcS
STf0h1uVQIuiG5yo0zM6chx1mfzNuU3sKelbTdTBEzSJZfUe7Aeca+bo8p6ooaqm
XIhdg7SqUNYLML5VrEVPA5STfUx84clCfjJ9Ot+4TuHcVMSUsG7TrlIWnd08gIgS
ZYKX0Np2fFudnwBLFhD3EbuGZl24OCM1bmXfHr8QWSnKb7/8PoBtYNxUnWi8Kwkv
cJ8f81kLd6R4n9oR4vE/+9oJIfVVgLlWxgrlCDtIhro22Hf5FnPWFg6gEm6UTPCW
POfChlhFAgMBAAECggEAM9CiX6oCye3Ll6s9Nx0dxtcsmnl95nPV3NJ4vSB3GNr9
6t8QkiGD1oZQGzQjnlfr1U3qHuXsrw+wdl8zPMmFQvhAkkRM5g/mK5WG0gXQj4NO
vkdyT/mdhwS/zcoC+CNuIvhkTjzogXlrCcvY4T0e0nkp+ESV41xfsxaCIgcZvwbW
MKq7+0fQYjxnhw2BStcxtzMbB9s3/lZzTOgO2l7RN5z8V3QMsXBGIC6F5qQ+OVVZ
vsAYwNfhPLMJd8ylLW6XaOTqcYWTvu5CjMU9BRrAJGn6ZVLip5yCr9ap9NllsGVb
YvXz+Slp++zEbyQns5ES2tvRKWhk0UcRzZDvQZuAoQKBgQDpz946sjdSi6vWAp7M
QEWYUoUfphL81k2lxIbk9yioXoBUnBeDnvhDLpFq0Ljt73Zt7ZNPU7KmWe2Pi+Rn
dES/zXJ/P+25ea0bQDKUftERvG5vECBiZRPXzBQAvizdNJPYCUrhHb0rAFp3BQAl
44s1b5FzjGG3WBqWypBFvilTOQKBgQDaSPa9SEoAHtAUI9JPjn/mr4ABO63xZ4ec
j63VRqJmgrjUmt7xPCVipSBwnXpDQfoohsmOURkC7QiwnGNDGQPigmC/yfk8Vd1z
XgdxJDnXYWaAIY3C0Nj8BPtJA/eQ6PRHJ2A3Ta65Fv/nk0nTsGH7JNA0YD4zlJKd
TJpE8gAxbQKBgGBVTuCsMPMHrQL+DWNmT8ZUqZjCmiwmN9PGxzVrSAsm9ITn0yBd
zTgQ5cU2vhr6gLcGHZ2fhInZn3F3V+HwG6tTAIvBUTcMFPCXYL+iCI3gLzf/Uvh3
YNeWs98ie+WgFhH6silSUXB4Ms2697akq+SWVT1gZ5pc6IecahjyIqCxAoGBANko
w4e1liEehmWy6XTKUIYATPltFPRXyftAmXDXb5NKM3UXifo2mv7TRj2i/VJSHfwZ
dAWIurhFdmK1gq7rAQlkKbpDxhd3WPOANSkjIAQc2ytXtj99JJE8p32RW8anavYq
vzblqpBqyDXrOwRFsoR2sEebA+auxVmGLueuVfDVAoGBAME7JQkpA6AMTa70QfJu
EIht+jDIgTbaqf1rdaNCB/EUn5oAv0GDXbh8kgTPPjd8n3V97mVM6DIwXlO1TkKU
A48a2VaddTR7mPcvguNtyrMRt7LG8/eyfXN1iRfs101DkTq1wlm4kIarQfEgBB4o
9/fH0NErMycumXLoETPK4ALi
-----END PRIVATE KEY-----
`
)

var testblock = "Stuff and nonsense to encode "

func TestGenerateDigestSignature(t *testing.T) {
pk, _ := PrivateKeyFromString([]byte(privateKeyG))
_, err := GenerateDigestSignature(pk, teststr)
func getPrivateKeys() ([]privateKey, error) {
pkcs1, err := PrivateKeyFromString([]byte(privateKeyG))
if err != nil {
return nil, err
}
pkcs8, err := PrivateKeyFromString([]byte(privateKey8))
if err != nil {
t.Error("Error generating signature", err)
return nil, err
}
return []privateKey{
{"pkcs#1", pkcs1},
{"pkcs#8", pkcs8},
}, nil
}

func TestGenerateSignature(t *testing.T) {
pk, _ := PrivateKeyFromString([]byte(privateKeyG))
_, err := GenerateSignature(pk, teststr)
if err != nil {
t.Error("Error generating signature", err)
func TestGenerateDigestSignature(t *testing.T) {
pks, _ := getPrivateKeys()
for _, pk := range pks {
signed, err := GenerateDigestSignature(pk.key, teststr)
if err != nil {
t.Error("Error generating signature", pk.name, err)
}
assert.Equalf(t, signature13, base64.StdEncoding.EncodeToString(signed),
"Signature doesn't match. Version=%+v, KeyType=%+v", "1.0", pk.name)
}
}

func TestPrivateEncrypt(t *testing.T) {
pk, _ := PrivateKeyFromString([]byte(privateKeyG))
_, err := privateEncrypt(pk, []byte(teststr))
if err != nil {
t.Error("Error encrypting", err)
func TestGenerateSignature(t *testing.T) {
pks, _ := getPrivateKeys()
for _, pk := range pks {
signed, err := GenerateSignature(pk.key, teststr)
if err != nil {
t.Error("Error generating signature", pk.name, err)
}
assert.Equalf(t, signature10, base64.StdEncoding.EncodeToString(signed),
"Signature doesn't match. Version=%+v, KeyType=%+v", "1.3", pk.name)
}
}

Expand Down