Documentation ¶
Overview ¶
Package srp implements the Secure Remote Password Protocol (Version 6a)
SRP-6a is a password-authenticated key agreement (PAKE) protocol where a client/user demonstrates to a server that they know the password without sending the password or any other information from which a password can be inferred.
The goal of SRP is for both client and server to generate the same session key (K), which they prove by sharing a hash (M) of several known parameters and attempting to replicate the value. Validating the value of M proves that the server and client are each aware of their long term secrets x (client secret) and v (server secret)
RFC 2945: The SRP Authentication and Key Exchange System https://tools.ietf.org/html/rfc2945
RFC 5054: Using the Secure Remote Password (SRP) Protocol for TLS Authentication https://tools.ietf.org/html/rfc5054
Operations
^: Denotes exponentiation operation |: Denotes concatenation %: Denotes modulo operation H(): Hash Function (eg. SHA256)
Roles
C: Client/User attempting authentication S: Server authenticating the client
Key
N, g: Group parameters (a large prime N, and a primitive root of N) I: An identifying username belonging to C p: A password belonging to C s: A salt belonging to C x: Private key derived from p and s; x = H(s|H(I|":"|p)) k: A multiplier parameter derived by both C and S; k = H(N, g) u: A scrambling parameter derived by both C and S; u = H(A, B) v: The password verifier belonging to S and derived from x; v = g^x % N a,A: Secret/Public ephemeral values belonging to C b,B: Secret/Public ephemeral values belonging to S M: Calculated proof of key generation K: Calculated shared key
Scenario: Client (C) establishes a password with Server (S)
- C selects a password p, salt s and computes x = H(s|H(I|":"|p)), v = g^x % N
- C submits v (password verifier), s, I (username) to S
- S stores v and s, indexed by I
Scenario: Client (C) demonstrates proof of password to Server (S)
Initial hash of shared public keys
- C generates secret/public ephemeral values a/A where A = g^a % N
- C submits I and A to S
- S generates secret/public ephemeral values b/B where B = (kv + g^b) % N
- S submits B and s to C
- C and S both calculate u = H(A, B)
Calculation of keys:
- C calculates Premaster Secret cPS = ((B - k (g^x)) ^ (a + ux)) % N
- S calculates Premaster Secret sPS = ((A * v^u) ^ b) % N
- C calculates M1 = H(H(N) XOR H(g), H(I), s, A, B, H(cPS))
- S calculates M2 = H(A, M1, H(sPS))
Confirmation of proof:
- C submits M1 and S confirms M1
- S submits M2 and C onfirms M2
Full authentication is as follows:
Client Server ---------- ---------- Calculate a, A I, A ---------> Calculate b, B <--------- B, s Calculate K, M1 M1 ---------> Calculate K, M2 Confirm M2 <--------- M2 Confirm M2
Index ¶
Examples ¶
Constants ¶
const ( // ErrNoGroupParams is returned when SRP group parameters N and G // are not initialized. ErrNoGroupParams = Error("srp.Group not initialized") // ErrNoPremasterKey is returned when a calculation is attempted // that requires the key. ErrNoPremasterKey = Error("premaster key required for calculation") // ErrBadClientProof is returned when the client submits invalid // proof. ErrBadClientProof = Error("invalid client proof received") // ErrNoHash is returned when a client or server attempts a calculation // with no hashing function set. ErrNoHash = Error("hash not initialized") // ErrCalcVerifier is returned when the client fails to calculate a // verifier value. ErrCalcVerifier = Error("failed to generate verifier") // ErrNoEphemeralKeys is returned when a calculation is done with missing // ephemeral keys A or B. ErrNoEphemeralKeys = Error("shared keys A/B not calculated") // ErrPublicKeyModuloZero is returned when a public key % N is 0. ErrPublicKeyModuloZero = Error("key % N cannot be 0") // ErrInvalidPrime is returned when a Group is created with an invalid prime // value. ErrInvalidPrime = Error("invalid prime value provided") // ErrInvalidPrimitiveRoot is returned when a Group is created with an invalid // primitive root. ErrInvalidPrimitiveRoot = Error("invalid primitive root provided") )
const ( // Group1024 is a primitive root and hexadecimal prime number. Group1024 = "2:0xEEAF0AB9ADB38DD69C33F80AFA8FC5E860726187" + "75FF3C0B9EA2314C9C256576D674DF7496EA81D3383B4813D692" + "C6E0E0D5D8E250B98BE48E495C1D6089DAD15DC7D7B46154D6B6" + "CE8EF4AD69B15D4982559B297BCF1885C529F566660E57EC68ED" + "BC3C05726CC02FD4CBF4976EAA9AFD5138FE8376435B9FC61D2F" + "C0EB06E3" // Group2048 is a primitive root and hexadecimal prime number. Group2048 = "2:0xAC6BDB41324A9A9BF166DE5E1389582FAF72B665" + "1987EE07FC3192943DB56050A37329CBB4A099ED8193E0757767" + "A13DD52312AB4B03310DCD7F48A9DA04FD50E8083969EDB767B0" + "CF6095179A163AB3661A05FBD5FAAAE82918A9962F0B93B855F9" + "7993EC975EEAA80D740ADBF4FF747359D041D5C33EA71D281E44" + "6B14773BCA97B43A23FB801676BD207A436C6481F1D2B9078717" + "461A5B9D32E688F87748544523B524B0D57D5EA77A2775D2ECFA" + "032CFBDBF52FB3786160279004E57AE6AF874E7303CE53299CCC" + "041C7BC308D82A5698F3A8D0C38271AE35F8E9DBFBB694B5C803" + "D89F7AE435DE236D525F54759B65E372FCD68EF20FA7111F9E4A" + "FF73" // Group4096 is a primitive root and hexadecimal prime number. Group4096 = "5:0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B" + "80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E34" + "04DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE38" + "6BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8" + "A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3" + "AD961C62F356208552BB9ED529077096966D670C354E4ABC9804" + "F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B27" + "83A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497C" + "EA956AE515D2261898FA051015728E5A8AAAC42DAD33170D0450" + "7A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7D" + "B3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3" + "D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18" + "177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5" + "AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" + "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583" + "E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C5947" + "4E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2" + "D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC1" + "86FFB7DC90A6C08F4DF435C934063199FFFFFFFFFFFFFFFF" // Group8192 is a primitive root and hexadecimal prime number. Group8192 = "19:0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628" + "B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3" + "404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C24" + "5E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE3" + "86BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB" + "8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA" + "3AD961C62F356208552BB9ED529077096966D670C354E4ABC980" + "4F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2" + "783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497" + "CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D045" + "07A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7" + "DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE" + "3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B1" + "8177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E" + "5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D" + "788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA258" + "3E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C594" + "74E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE" + "2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC" + "186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026C1D" + "4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382" + "F413001AEB06A53ED9027D831179727B0865A8918DA3EDBEBCF9" + "B14ED44CE6CBACED4BB1BDB7F1447E6CC254B332051512BD7AF4" + "26FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03F48" + "2D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97" + "FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4" + "154AACC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32" + "806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA5" + "6C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5" + "B0B7474D6E694F91E6DBE115974A3926F12FEE5E438777CB6A93" + "2DF8CD8BEC4D073B931BA3BC832B68D9DD300741FA7BF8AFC47E" + "D2576F6936BA424663AAB639C5AE4F5683423B4742BF1C978238" + "F16CBE39D652DE3FDB8BEFC848AD922222E04A4037C0713EB57A" + "81A23F0C73473FC646CEA306B4BCBC8862F8385DDFA9D4B7FA2C" + "087E879683303ED5BDD3A062B3CF5B3A278A66D2A13F83F44F82" + "DDF310EE074AB6A364597E899A0255DC164F31CC50846851DF9A" + "B48195DED7EA1B1D510BD7EE74D73FAF36BC31ECFA268359046F" + "4EB879F924009438B481C6CD7889A002ED5EE382BC9190DA6FC0" + "26E479558E4475677E9AA9E3050E2765694DFC81F56E880B96E7" + "160C980DD98EDD3DFFFFFFFFFFFFFFFFF" )
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type AuthClient ¶
type AuthClient interface { Enroll() (string, string, *big.Int, error) Auth() (string, *big.Int) ProveIdentity(*big.Int, string) (*big.Int, error) }
AuthClient is an interface to support client related requests for enrollment and authentication.
type AuthServer ¶
type AuthServer interface { ProcessEnroll(u, s string, v *big.Int) bool ProcessAuth(u, sa string, A, v *big.Int) (*big.Int, string, error) ProcessProof(cp *big.Int) (*big.Int, error) }
AuthServer is an interface to support client request validation.
type Client ¶
type Client struct { SRP // contains filtered or unexported fields }
Client represents an SRP Client. Client possesses a password and initiates enrollment and authentication against an SRP Server.
func NewDefaultClient ¶
NewDefaultClient returns an SRP Client preconfigured for parameters Group4096 and SHA256 hashing function.
func (*Client) Auth ¶
Auth prepares an authentication payload for an SRP server. We expect a Client to have already completed a RequestEnrollment prior to submitting an authentication request.
func (*Client) Enroll ¶
Enroll prepares an enrollment payload for an SRP server. We expect enrollment payload to be persisted on the server for future authentication.
func (*Client) IsProofValid ¶
IsProofValid validates a SRP Server's proof of session key.
type Group ¶
type Group struct { // Hex is the hexadecimal value for prime N Hex string // G is a primitive root of prime N G *big.Int // N is a large prime value N *big.Int }
Group represents constant parameters in the SRP protocol.
It is a combination of large prime value, N and a primitive root of N, known as G, used by both the client and server.
RFC 5054 Section 3.2 warns that due to the difficulty of calculating eligible prime values in real time, implementations of SRP should use pre-defined values from a trusted source. The values provided in this package come from RFC 5054 Appendix A.
Ref:
https://tools.ietf.org/html/rfc5054#section-3.2 https://tools.ietf.org/html/rfc5054#appendix-A
type SRP ¶
type SRP struct { // N is a large prime, referred to in RFC 5054 as N. N *big.Int // G is a primitive root of N, referred to in RFC 5054 as g. G *big.Int // H is a cryptographic hash. RFC 5054 defaults to SHA1. H crypto.Hash // I is a username, referred to in RFC 5054 as I. I string // S is a user's salt referred to in RFC 5054 as s. S string // Long term secret, RFC 5054 refers to this value as x // for the client and v for the server. Secret *big.Int PremasterKey *big.Int // contains filtered or unexported fields }
SRP represents the main parameters used in calculating a server/client shared key.
The srp/client and srp/server packages extend SRP from a client and server use-case perspective.
Example (Default) ¶
c, _ := NewDefaultClient("jane_doe_123", "my-password") s, _ := NewDefaultServer() // Client salt and verifier and returns public key. _, salt, verifier, _ := c.Enroll() username, pubKeyA := c.Auth() // Server processes auth credentials pubKeyB, saltB, _ := s.ProcessAuth(username, salt, pubKeyA, verifier) clientProof, err := c.ProveIdentity(pubKeyB, saltB) fmt.Println(err) serverProof, err := s.ProcessProof(clientProof) fmt.Println(err) ok := c.IsProofValid(serverProof) fmt.Println(ok)
Output: <nil> <nil> true
Example (SpecifyGroupAndHash) ¶
g, _ := NewGroup(Group8192) c, _ := NewClient(crypto.SHA512, g, "jane_doe_123", "my-password") s, _ := NewServer(crypto.SHA512, g) // Client salt and verifier and returns public key. _, salt, verifier, _ := c.Enroll() username, pubKeyA := c.Auth() // Server processes auth credentials pubKeyB, saltB, _ := s.ProcessAuth(username, salt, pubKeyA, verifier) clientProof, err := c.ProveIdentity(pubKeyB, saltB) fmt.Println(err) serverProof, err := s.ProcessProof(clientProof) fmt.Println(err) ok := c.IsProofValid(serverProof) fmt.Println(ok)
Output: <nil> <nil> true
func NewDefaultSRP ¶
NewDefaultSRP returns an SRP environment preconfigured for parameters Group4096 and SHA256 for a hashing function.
type Server ¶
type Server struct {
SRP
}
Server represents an SRP Server. Server validates a Client's enrollment and authentication.
func NewDefaultServer ¶
NewDefaultServer returns an SRP server preconfigured for parameters Group4096 and SHA256 hashing function.
func (*Server) IsProofValid ¶
IsProofValid validates a SRP Client's proof of session key.
func (*Server) ProcessAuth ¶
ProcessAuth ackwnowledges an authentication request from a pre-enrolled SRP Client. Credentials should be received from the SRP client. Salt and verifier should be retrieved from some secure persisted storage prior to this call. Retreival of cr2 is outside the scope of this package.
func (*Server) ProcessEnroll ¶
ProcessEnroll acknowledges an enrollment payload from an SRP Client. It returns true if valid credentials have been submitted.