Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

crypto.go 3.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. // Copyright (c) 2018 Shivaram Lingamneni <slingamn@cs.stanford.edu>
  2. // released under the MIT license
  3. package utils
  4. import (
  5. "crypto/rand"
  6. "crypto/sha256"
  7. "crypto/subtle"
  8. "crypto/tls"
  9. "encoding/base32"
  10. "encoding/base64"
  11. "encoding/hex"
  12. "errors"
  13. "net"
  14. "strings"
  15. "time"
  16. )
  17. var (
  18. // slingamn's own private b32 alphabet, removing 1, l, o, and 0
  19. B32Encoder = base32.NewEncoding("abcdefghijkmnpqrstuvwxyz23456789").WithPadding(base32.NoPadding)
  20. ErrInvalidCertfp = errors.New("Invalid certfp")
  21. ErrNoPeerCerts = errors.New("No certfp available")
  22. ErrNotTLS = errors.New("Connection is not TLS")
  23. )
  24. const (
  25. SecretTokenLength = 26
  26. )
  27. // generate a secret token that cannot be brute-forced via online attacks
  28. func GenerateSecretToken() string {
  29. // 128 bits of entropy are enough to resist any online attack:
  30. var buf [16]byte
  31. rand.Read(buf[:])
  32. // 26 ASCII characters, should be fine for most purposes
  33. return B32Encoder.EncodeToString(buf[:])
  34. }
  35. // "munge" a secret token to a new value. requirements:
  36. // 1. MUST be roughly as unlikely to collide with `GenerateSecretToken` outputs
  37. // as those outputs are with each other
  38. // 2. SHOULD be deterministic (motivation: if a JOIN line has msgid x,
  39. // create a deterministic msgid y for the fake HistServ PRIVMSG that "replays" it)
  40. // 3. SHOULD be in the same "namespace" as `GenerateSecretToken` outputs
  41. // (same length and character set)
  42. func MungeSecretToken(token string) (result string) {
  43. bytes, err := B32Encoder.DecodeString(token)
  44. if err != nil {
  45. // this should never happen
  46. return GenerateSecretToken()
  47. }
  48. // add 1 with carrying
  49. for i := len(bytes) - 1; 0 <= i; i -= 1 {
  50. bytes[i] += 1
  51. if bytes[i] != 0 {
  52. break
  53. } // else: overflow, carry to the next place
  54. }
  55. return B32Encoder.EncodeToString(bytes)
  56. }
  57. // securely check if a supplied token matches a stored token
  58. func SecretTokensMatch(storedToken string, suppliedToken string) bool {
  59. // XXX fix a potential gotcha: if the stored token is uninitialized,
  60. // then nothing should match it, not even supplying an empty token.
  61. if len(storedToken) == 0 {
  62. return false
  63. }
  64. return subtle.ConstantTimeCompare([]byte(storedToken), []byte(suppliedToken)) == 1
  65. }
  66. // generate a 256-bit secret key that can be written into a config file
  67. func GenerateSecretKey() string {
  68. var buf [32]byte
  69. rand.Read(buf[:])
  70. return base64.RawURLEncoding.EncodeToString(buf[:])
  71. }
  72. // Normalize openssl-formatted certfp's to oragono's format
  73. func NormalizeCertfp(certfp string) (result string, err error) {
  74. result = strings.ToLower(strings.Replace(certfp, ":", "", -1))
  75. decoded, err := hex.DecodeString(result)
  76. if err != nil || len(decoded) != 32 {
  77. return "", ErrInvalidCertfp
  78. }
  79. return
  80. }
  81. func GetCertFP(conn net.Conn, handshakeTimeout time.Duration) (result string, err error) {
  82. tlsConn, isTLS := conn.(*tls.Conn)
  83. if !isTLS {
  84. return "", ErrNotTLS
  85. }
  86. // ensure handshake is performed
  87. tlsConn.SetDeadline(time.Now().Add(handshakeTimeout))
  88. err = tlsConn.Handshake()
  89. tlsConn.SetDeadline(time.Time{})
  90. if err != nil {
  91. return "", err
  92. }
  93. peerCerts := tlsConn.ConnectionState().PeerCertificates
  94. if len(peerCerts) < 1 {
  95. return "", ErrNoPeerCerts
  96. }
  97. rawCert := sha256.Sum256(peerCerts[0].Raw)
  98. fingerprint := hex.EncodeToString(rawCert[:])
  99. return fingerprint, nil
  100. }