crypto_test.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. package p2p
  2. import (
  3. "bytes"
  4. "crypto/ecdsa"
  5. "crypto/rand"
  6. "net"
  7. "testing"
  8. "github.com/ethereum/go-ethereum/crypto"
  9. "github.com/ethereum/go-ethereum/crypto/ecies"
  10. )
  11. func TestPublicKeyEncoding(t *testing.T) {
  12. prv0, _ := crypto.GenerateKey() // = ecdsa.GenerateKey(crypto.S256(), rand.Reader)
  13. pub0 := &prv0.PublicKey
  14. pub0s := crypto.FromECDSAPub(pub0)
  15. pub1, err := importPublicKey(pub0s)
  16. if err != nil {
  17. t.Errorf("%v", err)
  18. }
  19. eciesPub1 := ecies.ImportECDSAPublic(pub1)
  20. if eciesPub1 == nil {
  21. t.Errorf("invalid ecdsa public key")
  22. }
  23. pub1s, err := exportPublicKey(pub1)
  24. if err != nil {
  25. t.Errorf("%v", err)
  26. }
  27. if len(pub1s) != 64 {
  28. t.Errorf("wrong length expect 64, got", len(pub1s))
  29. }
  30. pub2, err := importPublicKey(pub1s)
  31. if err != nil {
  32. t.Errorf("%v", err)
  33. }
  34. pub2s, err := exportPublicKey(pub2)
  35. if err != nil {
  36. t.Errorf("%v", err)
  37. }
  38. if !bytes.Equal(pub1s, pub2s) {
  39. t.Errorf("exports dont match")
  40. }
  41. pub2sEC := crypto.FromECDSAPub(pub2)
  42. if !bytes.Equal(pub0s, pub2sEC) {
  43. t.Errorf("exports dont match")
  44. }
  45. }
  46. func TestSharedSecret(t *testing.T) {
  47. prv0, _ := crypto.GenerateKey() // = ecdsa.GenerateKey(crypto.S256(), rand.Reader)
  48. pub0 := &prv0.PublicKey
  49. prv1, _ := crypto.GenerateKey()
  50. pub1 := &prv1.PublicKey
  51. ss0, err := ecies.ImportECDSA(prv0).GenerateShared(ecies.ImportECDSAPublic(pub1), sskLen, sskLen)
  52. if err != nil {
  53. return
  54. }
  55. ss1, err := ecies.ImportECDSA(prv1).GenerateShared(ecies.ImportECDSAPublic(pub0), sskLen, sskLen)
  56. if err != nil {
  57. return
  58. }
  59. t.Logf("Secret:\n%v %x\n%v %x", len(ss0), ss0, len(ss0), ss1)
  60. if !bytes.Equal(ss0, ss1) {
  61. t.Errorf("dont match :(")
  62. }
  63. }
  64. func TestCryptoHandshake(t *testing.T) {
  65. testCryptoHandshake(newkey(), newkey(), nil, t)
  66. }
  67. func TestCryptoHandshakeWithToken(t *testing.T) {
  68. sessionToken := make([]byte, shaLen)
  69. rand.Read(sessionToken)
  70. testCryptoHandshake(newkey(), newkey(), sessionToken, t)
  71. }
  72. func testCryptoHandshake(prv0, prv1 *ecdsa.PrivateKey, sessionToken []byte, t *testing.T) {
  73. var err error
  74. // pub0 := &prv0.PublicKey
  75. pub1 := &prv1.PublicKey
  76. // pub0s := crypto.FromECDSAPub(pub0)
  77. pub1s := crypto.FromECDSAPub(pub1)
  78. // simulate handshake by feeding output to input
  79. // initiator sends handshake 'auth'
  80. auth, initNonce, randomPrivKey, err := authMsg(prv0, pub1s, sessionToken)
  81. if err != nil {
  82. t.Errorf("%v", err)
  83. }
  84. t.Logf("-> %v", hexkey(auth))
  85. // receiver reads auth and responds with response
  86. response, remoteRecNonce, remoteInitNonce, _, remoteRandomPrivKey, remoteInitRandomPubKey, err := authResp(auth, sessionToken, prv1)
  87. if err != nil {
  88. t.Errorf("%v", err)
  89. }
  90. t.Logf("<- %v\n", hexkey(response))
  91. // initiator reads receiver's response and the key exchange completes
  92. recNonce, remoteRandomPubKey, _, err := completeHandshake(response, prv0)
  93. if err != nil {
  94. t.Errorf("completeHandshake error: %v", err)
  95. }
  96. // now both parties should have the same session parameters
  97. initSessionToken, err := newSession(initNonce, recNonce, randomPrivKey, remoteRandomPubKey)
  98. if err != nil {
  99. t.Errorf("newSession error: %v", err)
  100. }
  101. recSessionToken, err := newSession(remoteInitNonce, remoteRecNonce, remoteRandomPrivKey, remoteInitRandomPubKey)
  102. if err != nil {
  103. t.Errorf("newSession error: %v", err)
  104. }
  105. // fmt.Printf("\nauth (%v) %x\n\nresp (%v) %x\n\n", len(auth), auth, len(response), response)
  106. // fmt.Printf("\nauth %x\ninitNonce %x\nresponse%x\nremoteRecNonce %x\nremoteInitNonce %x\nremoteRandomPubKey %x\nrecNonce %x\nremoteInitRandomPubKey %x\ninitSessionToken %x\n\n", auth, initNonce, response, remoteRecNonce, remoteInitNonce, remoteRandomPubKey, recNonce, remoteInitRandomPubKey, initSessionToken)
  107. if !bytes.Equal(initNonce, remoteInitNonce) {
  108. t.Errorf("nonces do not match")
  109. }
  110. if !bytes.Equal(recNonce, remoteRecNonce) {
  111. t.Errorf("receiver nonces do not match")
  112. }
  113. if !bytes.Equal(initSessionToken, recSessionToken) {
  114. t.Errorf("session tokens do not match")
  115. }
  116. }
  117. func TestHandshake(t *testing.T) {
  118. defer testlog(t).detach()
  119. prv0, _ := crypto.GenerateKey()
  120. prv1, _ := crypto.GenerateKey()
  121. pub0s, _ := exportPublicKey(&prv0.PublicKey)
  122. pub1s, _ := exportPublicKey(&prv1.PublicKey)
  123. rw0, rw1 := net.Pipe()
  124. tokens := make(chan []byte)
  125. go func() {
  126. token, err := outboundEncHandshake(rw0, prv0, pub1s, nil)
  127. if err != nil {
  128. t.Errorf("outbound side error: %v", err)
  129. }
  130. tokens <- token
  131. }()
  132. go func() {
  133. token, remotePubkey, err := inboundEncHandshake(rw1, prv1, nil)
  134. if err != nil {
  135. t.Errorf("inbound side error: %v", err)
  136. }
  137. if !bytes.Equal(remotePubkey, pub0s) {
  138. t.Errorf("inbound side returned wrong remote pubkey\n got: %x\n want: %x", remotePubkey, pub0s)
  139. }
  140. tokens <- token
  141. }()
  142. t1, t2 := <-tokens, <-tokens
  143. if !bytes.Equal(t1, t2) {
  144. t.Error("session token mismatch")
  145. }
  146. }