Source File
kex.go
Belonging Package
golang.org/x/crypto/ssh
package ssh
import (
)
const (
kexAlgoDH1SHA1 = "diffie-hellman-group1-sha1"
kexAlgoDH14SHA1 = "diffie-hellman-group14-sha1"
kexAlgoECDH256 = "ecdh-sha2-nistp256"
kexAlgoECDH384 = "ecdh-sha2-nistp384"
kexAlgoECDH521 = "ecdh-sha2-nistp521"
kexAlgoCurve25519SHA256 = "curve25519-sha256@libssh.org"
kexAlgoDHGEXSHA1 = "diffie-hellman-group-exchange-sha1"
kexAlgoDHGEXSHA256 = "diffie-hellman-group-exchange-sha256"
)
type handshakeMagics struct {
clientVersion, serverVersion []byte
clientKexInit, serverKexInit []byte
}
func ( *handshakeMagics) ( io.Writer) {
writeString(, .clientVersion)
writeString(, .serverVersion)
writeString(, .clientKexInit)
writeString(, .serverKexInit)
}
Server(p packetConn, rand io.Reader, magics *handshakeMagics, s Signer) (*kexResult, error)
Client(p packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error)
}
type dhGroup struct {
g, p, pMinus1 *big.Int
}
func ( *dhGroup) (, *big.Int) (*big.Int, error) {
if .Cmp(bigOne) <= 0 || .Cmp(.pMinus1) >= 0 {
return nil, errors.New("ssh: DH parameter out of bounds")
}
return new(big.Int).Exp(, , .p), nil
}
func ( *dhGroup) ( packetConn, io.Reader, *handshakeMagics) (*kexResult, error) {
:= crypto.SHA1
var *big.Int
for {
var error
if , = rand.Int(, .pMinus1); != nil {
return nil,
}
if .Sign() > 0 {
break
}
}
:= new(big.Int).Exp(.g, , .p)
:= kexDHInitMsg{
X: ,
}
if := .writePacket(Marshal(&)); != nil {
return nil,
}
, := .readPacket()
if != nil {
return nil,
}
var kexDHReplyMsg
if = Unmarshal(, &); != nil {
return nil,
}
, := .diffieHellman(.Y, )
if != nil {
return nil,
}
:= .New()
.write()
writeString(, .HostKey)
writeInt(, )
writeInt(, .Y)
:= make([]byte, intLength())
marshalInt(, )
.Write()
return &kexResult{
H: .Sum(nil),
K: ,
HostKey: .HostKey,
Signature: .Signature,
Hash: crypto.SHA1,
}, nil
}
func ( *dhGroup) ( packetConn, io.Reader, *handshakeMagics, Signer) ( *kexResult, error) {
:= crypto.SHA1
, := .readPacket()
if != nil {
return
}
var kexDHInitMsg
if = Unmarshal(, &); != nil {
return
}
var *big.Int
for {
if , = rand.Int(, .pMinus1); != nil {
return
}
if .Sign() > 0 {
break
}
}
:= new(big.Int).Exp(.g, , .p)
, := .diffieHellman(.X, )
if != nil {
return nil,
}
:= .PublicKey().Marshal()
:= .New()
.write()
writeString(, )
writeInt(, .X)
writeInt(, )
:= make([]byte, intLength())
marshalInt(, )
.Write()
:= .Sum(nil)
type ecdh struct {
curve elliptic.Curve
}
func ( *ecdh) ( packetConn, io.Reader, *handshakeMagics) (*kexResult, error) {
, := ecdsa.GenerateKey(.curve, )
if != nil {
return nil,
}
:= kexECDHInitMsg{
ClientPubKey: elliptic.Marshal(.curve, .PublicKey.X, .PublicKey.Y),
}
:= Marshal(&)
if := .writePacket(); != nil {
return nil,
}
, := .readPacket()
if != nil {
return nil,
}
var kexECDHReplyMsg
if = Unmarshal(, &); != nil {
return nil,
}
, , := unmarshalECKey(.curve, .EphemeralPubKey)
if != nil {
return nil,
}
, := .curve.ScalarMult(, , .D.Bytes())
:= ecHash(.curve).New()
.write()
writeString(, .HostKey)
writeString(, .ClientPubKey)
writeString(, .EphemeralPubKey)
:= make([]byte, intLength())
marshalInt(, )
.Write()
return &kexResult{
H: .Sum(nil),
K: ,
HostKey: .HostKey,
Signature: .Signature,
Hash: ecHash(.curve),
}, nil
}
return true
}
func ( *ecdh) ( packetConn, io.Reader, *handshakeMagics, Signer) ( *kexResult, error) {
, := .readPacket()
if != nil {
return nil,
}
var kexECDHInitMsg
if = Unmarshal(, &); != nil {
return nil,
}
, , := unmarshalECKey(.curve, .ClientPubKey)
if != nil {
return nil,
}
, := .curve.ScalarMult(, , .D.Bytes())
:= ecHash(.curve).New()
.write()
writeString(, )
writeString(, .ClientPubKey)
writeString(, )
:= make([]byte, intLength())
marshalInt(, )
.Write()
:= .Sum(nil)
, := signAndMarshal(, , )
if != nil {
return nil,
}
:= kexECDHReplyMsg{
EphemeralPubKey: ,
HostKey: ,
Signature: ,
}
:= Marshal(&)
if := .writePacket(); != nil {
return nil,
}
return &kexResult{
H: ,
K: ,
HostKey: .HostKey,
Signature: ,
Hash: ecHash(.curve),
}, nil
}
var kexAlgoMap = map[string]kexAlgorithm{}
, := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF", 16)
kexAlgoMap[kexAlgoDH1SHA1] = &dhGroup{
g: new(big.Int).SetInt64(2),
p: ,
pMinus1: new(big.Int).Sub(, bigOne),
}
, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16)
kexAlgoMap[kexAlgoDH14SHA1] = &dhGroup{
g: new(big.Int).SetInt64(2),
p: ,
pMinus1: new(big.Int).Sub(, bigOne),
}
kexAlgoMap[kexAlgoECDH521] = &ecdh{elliptic.P521()}
kexAlgoMap[kexAlgoECDH384] = &ecdh{elliptic.P384()}
kexAlgoMap[kexAlgoECDH256] = &ecdh{elliptic.P256()}
kexAlgoMap[kexAlgoCurve25519SHA256] = &curve25519sha256{}
kexAlgoMap[kexAlgoDHGEXSHA1] = &dhGEXSHA{hashFunc: crypto.SHA1}
kexAlgoMap[kexAlgoDHGEXSHA256] = &dhGEXSHA{hashFunc: crypto.SHA256}
}
type curve25519sha256 struct{}
type curve25519KeyPair struct {
priv [32]byte
pub [32]byte
}
func ( *curve25519KeyPair) ( io.Reader) error {
if , := io.ReadFull(, .priv[:]); != nil {
return
}
curve25519.ScalarBaseMult(&.pub, &.priv)
return nil
}
var curve25519Zeros [32]byte
func ( *curve25519sha256) ( packetConn, io.Reader, *handshakeMagics) (*kexResult, error) {
var curve25519KeyPair
if := .generate(); != nil {
return nil,
}
if := .writePacket(Marshal(&kexECDHInitMsg{.pub[:]})); != nil {
return nil,
}
, := .readPacket()
if != nil {
return nil,
}
var kexECDHReplyMsg
if = Unmarshal(, &); != nil {
return nil,
}
if len(.EphemeralPubKey) != 32 {
return nil, errors.New("ssh: peer's curve25519 public value has wrong length")
}
var , [32]byte
copy([:], .EphemeralPubKey)
curve25519.ScalarMult(&, &.priv, &)
if subtle.ConstantTimeCompare([:], curve25519Zeros[:]) == 1 {
return nil, errors.New("ssh: peer's curve25519 public value has wrong order")
}
:= crypto.SHA256.New()
.write()
writeString(, .HostKey)
writeString(, .pub[:])
writeString(, .EphemeralPubKey)
:= new(big.Int).SetBytes([:])
:= make([]byte, intLength())
marshalInt(, )
.Write()
return &kexResult{
H: .Sum(nil),
K: ,
HostKey: .HostKey,
Signature: .Signature,
Hash: crypto.SHA256,
}, nil
}
func ( *curve25519sha256) ( packetConn, io.Reader, *handshakeMagics, Signer) ( *kexResult, error) {
, := .readPacket()
if != nil {
return
}
var kexECDHInitMsg
if = Unmarshal(, &); != nil {
return
}
if len(.ClientPubKey) != 32 {
return nil, errors.New("ssh: peer's curve25519 public value has wrong length")
}
var curve25519KeyPair
if := .generate(); != nil {
return nil,
}
var , [32]byte
copy([:], .ClientPubKey)
curve25519.ScalarMult(&, &.priv, &)
if subtle.ConstantTimeCompare([:], curve25519Zeros[:]) == 1 {
return nil, errors.New("ssh: peer's curve25519 public value has wrong order")
}
:= .PublicKey().Marshal()
:= crypto.SHA256.New()
.write()
writeString(, )
writeString(, .ClientPubKey)
writeString(, .pub[:])
:= new(big.Int).SetBytes([:])
:= make([]byte, intLength())
marshalInt(, )
.Write()
:= .Sum(nil)
, := signAndMarshal(, , )
if != nil {
return nil,
}
:= kexECDHReplyMsg{
EphemeralPubKey: .pub[:],
HostKey: ,
Signature: ,
}
if := .writePacket(Marshal(&)); != nil {
return nil,
}
return &kexResult{
H: ,
K: ,
HostKey: ,
Signature: ,
Hash: crypto.SHA256,
}, nil
}
type dhGEXSHA struct {
g, p *big.Int
hashFunc crypto.Hash
}
const (
dhGroupExchangeMinimumBits = 2048
dhGroupExchangePreferredBits = 2048
dhGroupExchangeMaximumBits = 8192
)
func ( *dhGEXSHA) (, *big.Int) (*big.Int, error) {
if .Sign() <= 0 || .Cmp(.p) >= 0 {
return nil, fmt.Errorf("ssh: DH parameter out of bounds")
}
return new(big.Int).Exp(, , .p), nil
}
:= kexDHGexRequestMsg{
MinBits: dhGroupExchangeMinimumBits,
PreferedBits: dhGroupExchangePreferredBits,
MaxBits: dhGroupExchangeMaximumBits,
}
if := .writePacket(Marshal(&)); != nil {
return nil,
}
, := .readPacket()
if != nil {
return nil,
}
var kexDHGexGroupMsg
if = Unmarshal(, &); != nil {
return nil,
}
, = .readPacket()
if != nil {
return nil,
}
var kexDHGexReplyMsg
if = Unmarshal(, &); != nil {
return nil,
}
, := .diffieHellman(.Y, )
if != nil {
return nil,
}
if .Cmp() != 1 && .Cmp() != -1 {
return nil, fmt.Errorf("ssh: derived k is not safe")
}
:= .hashFunc.New()
.write()
writeString(, .HostKey)
binary.Write(, binary.BigEndian, uint32(dhGroupExchangeMinimumBits))
binary.Write(, binary.BigEndian, uint32(dhGroupExchangePreferredBits))
binary.Write(, binary.BigEndian, uint32(dhGroupExchangeMaximumBits))
writeInt(, .p)
writeInt(, .g)
writeInt(, )
writeInt(, .Y)
:= make([]byte, intLength())
marshalInt(, )
.Write()
return &kexResult{
H: .Sum(nil),
K: ,
HostKey: .HostKey,
Signature: .Signature,
Hash: .hashFunc,
}, nil
}
, := .readPacket()
if != nil {
return
}
var kexDHGexRequestMsg
if = Unmarshal(, &); != nil {
return
}
if .MinBits > .PreferedBits {
.MinBits = .PreferedBits
}
if .MaxBits < .PreferedBits {
.MaxBits = .PreferedBits
}
, := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16)
.p =
.g = big.NewInt(2)
:= kexDHGexGroupMsg{
P: .p,
G: .g,
}
if := .writePacket(Marshal(&)); != nil {
return nil,
}
, = .readPacket()
if != nil {
return
}
var kexDHGexInitMsg
if = Unmarshal(, &); != nil {
return
}
var = &big.Int{}
.Rsh(.p, 1)
, := rand.Int(, )
if != nil {
return
}
:= new(big.Int).Exp(.g, , .p)
, := .diffieHellman(.X, )
if != nil {
return nil,
}
:= .PublicKey().Marshal()
:= .hashFunc.New()
.write()
writeString(, )
binary.Write(, binary.BigEndian, uint32(dhGroupExchangeMinimumBits))
binary.Write(, binary.BigEndian, uint32(dhGroupExchangePreferredBits))
binary.Write(, binary.BigEndian, uint32(dhGroupExchangeMaximumBits))
writeInt(, .p)
writeInt(, .g)
writeInt(, .X)
writeInt(, )
:= make([]byte, intLength())
marshalInt(, )
.Write()
:= .Sum(nil)
![]() |
The pages are generated with Golds v0.3.2-preview. (GOOS=darwin GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |