mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
141 lines
3.0 KiB
Go
141 lines
3.0 KiB
Go
package srp
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"math/big"
|
|
)
|
|
|
|
type SRPClient struct {
|
|
Params *SRPParams
|
|
Secret1 *big.Int
|
|
Multiplier *big.Int
|
|
A *big.Int
|
|
X *big.Int
|
|
M1 []byte
|
|
M2 []byte
|
|
K []byte
|
|
u *big.Int
|
|
s *big.Int
|
|
}
|
|
|
|
func NewClient(params *SRPParams, identity, password, secret1 []byte) *SRPClient {
|
|
multiplier := getMultiplier(params)
|
|
secret1Int := intFromBytes(secret1)
|
|
Ab := getA(params, secret1Int)
|
|
A := intFromBytes(Ab)
|
|
x := getx(params, []byte(""), identity, password) // salt has to be set using SetSalt
|
|
|
|
return &SRPClient{
|
|
Params: params,
|
|
Multiplier: multiplier,
|
|
Secret1: secret1Int,
|
|
A: A,
|
|
X: x,
|
|
}
|
|
}
|
|
|
|
func (c *SRPClient) ComputeA() []byte {
|
|
return intToBytes(c.A)
|
|
}
|
|
|
|
// ComputeVerifier returns a verifier that is calculated as described in
|
|
// Section 3 of [SRP-RFC]
|
|
func ComputeVerifier(params *SRPParams, salt, identity, password []byte) []byte {
|
|
x := getx(params, salt, identity, password)
|
|
vNum := new(big.Int)
|
|
vNum.Exp(params.G, x, params.N)
|
|
|
|
return padToN(vNum, params)
|
|
}
|
|
|
|
func (c *SRPClient) SetB(Bb []byte) {
|
|
B := intFromBytes(Bb)
|
|
u := getu(c.Params, c.A, B)
|
|
S := clientGetS(c.Params, c.Multiplier, c.X, c.Secret1, B, u)
|
|
|
|
c.K = getK(c.Params, S)
|
|
c.M1 = getM1(c.Params, intToBytes(c.A), Bb, c.K) // modified S -> c.K
|
|
c.M2 = getM2(c.Params, intToBytes(c.A), c.M1, c.K)
|
|
|
|
c.u = u // Only for tests
|
|
c.s = intFromBytes(S) // Only for tests
|
|
}
|
|
|
|
func (c *SRPClient) SetSalt(salt, identity, password []byte) {
|
|
c.X = getx(c.Params, salt, identity, password) //Overwrite
|
|
}
|
|
|
|
func (c *SRPClient) ComputeM1() []byte {
|
|
if c.M1 == nil {
|
|
panic("Incomplete protocol")
|
|
}
|
|
|
|
return c.M1
|
|
}
|
|
|
|
func (c *SRPClient) ComputeK() []byte {
|
|
return c.K
|
|
}
|
|
|
|
func (c *SRPClient) CheckM2(M2 []byte) error {
|
|
if !bytes.Equal(c.M2, M2) {
|
|
return errors.New("M2 didn't check")
|
|
} else {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func getA(params *SRPParams, a *big.Int) []byte {
|
|
ANum := new(big.Int)
|
|
ANum.Exp(params.G, a, params.N)
|
|
return padToN(ANum, params)
|
|
}
|
|
|
|
func clientGetS(params *SRPParams, k, x, a, B, u *big.Int) []byte {
|
|
BLessThan0 := B.Cmp(big.NewInt(0)) <= 0
|
|
NLessThanB := params.N.Cmp(B) <= 0
|
|
if BLessThan0 || NLessThanB {
|
|
panic("invalid server-supplied 'B', must be 1..N-1")
|
|
}
|
|
|
|
result1 := new(big.Int)
|
|
result1.Exp(params.G, x, params.N)
|
|
|
|
result2 := new(big.Int)
|
|
result2.Mul(k, result1)
|
|
|
|
result3 := new(big.Int)
|
|
result3.Sub(B, result2)
|
|
|
|
result4 := new(big.Int)
|
|
result4.Mul(u, x)
|
|
|
|
result5 := new(big.Int)
|
|
result5.Add(a, result4)
|
|
|
|
result6 := new(big.Int)
|
|
result6.Exp(result3, result5, params.N)
|
|
|
|
result7 := new(big.Int)
|
|
result7.Mod(result6, params.N)
|
|
|
|
return padToN(result7, params)
|
|
}
|
|
|
|
func getx(params *SRPParams, salt, I, P []byte) *big.Int {
|
|
var ipBytes []byte
|
|
ipBytes = append(ipBytes, I...)
|
|
ipBytes = append(ipBytes, []byte(":")...)
|
|
ipBytes = append(ipBytes, P...)
|
|
|
|
hashIP := params.Hash.New()
|
|
hashIP.Write(ipBytes)
|
|
|
|
hashX := params.Hash.New()
|
|
hashX.Write(salt)
|
|
hashX.Write(hashToBytes(hashIP))
|
|
|
|
return hashToInt(hashX)
|
|
}
|