roughtime.googlesource.com/roughtime.git@v0.0.0-20201210012726-dd529367052d/go/server/server.go (about) 1 // Copyright 2016 The Roughtime Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. */ 14 15 // server is a very basic Roughtime server. 16 // 17 // First, run with the flag -generate-key. This will print out a private key 18 // and a JSON template for the server. Put the private key (as hex) in a file 19 // named "priv" and then run with no arguments. 20 package main 21 22 // TODO(agl): add a test once the client functionality has landed. 23 24 import ( 25 "bytes" 26 "crypto/rand" 27 "encoding/hex" 28 "encoding/json" 29 "errors" 30 "flag" 31 "fmt" 32 "io/ioutil" 33 "log" 34 "net" 35 "os" 36 "time" 37 38 "golang.org/x/crypto/ed25519" 39 "roughtime.googlesource.com/go/config" 40 "roughtime.googlesource.com/go/protocol" 41 ) 42 43 var ( 44 genKey = flag.Bool("generate-key", false, "Generate a new key pair") 45 privateKeyFile = flag.String("private-key", "priv", "Filename of the private key (hex encoded)") 46 port = flag.Int("port", 5333, "Port number to listen on") 47 ) 48 49 func main() { 50 flag.Parse() 51 52 var err error 53 if *genKey { 54 err = generateKeyPair() 55 } else { 56 err = serveForever() 57 } 58 59 if err != nil { 60 fmt.Fprintf(os.Stderr, "%s\n", err) 61 os.Exit(1) 62 } 63 } 64 65 func serveForever() error { 66 privateKeyHex, err := ioutil.ReadFile(*privateKeyFile) 67 if err != nil { 68 return errors.New("Cannot open private key: " + err.Error()) 69 } 70 71 privateKey, err := hex.DecodeString(string(bytes.TrimSpace(privateKeyHex))) 72 if err != nil { 73 return errors.New("Cannot parse private key: " + err.Error()) 74 } 75 76 conn, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.IPv4(0, 0, 0, 0), Port: *port}) 77 if err != nil { 78 return errors.New("Cannot listen on port: " + err.Error()) 79 } 80 81 onlinePublicKey, onlinePrivateKey, err := ed25519.GenerateKey(rand.Reader) 82 if err != nil { 83 return errors.New("Cannot generate private key: " + err.Error()) 84 } 85 86 // As this is just an example, the certificate is created covering the 87 // maximum possible range. 88 cert, err := protocol.CreateCertificate(0, ^uint64(0), onlinePublicKey, privateKey) 89 if err != nil { 90 return errors.New("Cannot generate certificate: " + err.Error()) 91 } 92 93 log.Printf("Processing requests on port %d", *port) 94 95 var packetBuf [protocol.MinRequestSize]byte 96 97 for { 98 n, sourceAddr, err := conn.ReadFromUDP(packetBuf[:]) 99 if err != nil { 100 log.Print(err) 101 } 102 103 if n < protocol.MinRequestSize { 104 continue 105 } 106 107 packet, err := protocol.Decode(packetBuf[:n]) 108 if err != nil { 109 continue 110 } 111 112 nonce, ok := packet[protocol.TagNonce] 113 if !ok || len(nonce) != protocol.NonceSize { 114 continue 115 } 116 117 midpoint := uint64(time.Now().UnixNano() / 1000) 118 radius := uint32(1000000) 119 120 replies, err := protocol.CreateReplies([][]byte{nonce}, midpoint, radius, cert, onlinePrivateKey) 121 if err != nil { 122 log.Print(err) 123 continue 124 } 125 126 if len(replies) != 1 { 127 continue 128 } 129 130 conn.WriteToUDP(replies[0], sourceAddr) 131 } 132 } 133 134 func generateKeyPair() error { 135 rootPublic, rootPrivate, err := ed25519.GenerateKey(rand.Reader) 136 if err != nil { 137 return err 138 } 139 140 fmt.Printf("Private key: %x\n\n", rootPrivate) 141 142 exampleConfig := config.ServersJSON{ 143 Servers: []config.Server{ 144 config.Server{ 145 Name: "FIXME", 146 PublicKeyType: "ed25519", 147 PublicKey: rootPublic, 148 Addresses: []config.ServerAddress{ 149 config.ServerAddress{ 150 Protocol: "udp", 151 Address: "FIXME", 152 }, 153 }, 154 }, 155 }, 156 } 157 158 jsonBytes, err := json.MarshalIndent(exampleConfig, "", " ") 159 if err != nil { 160 return err 161 } 162 163 os.Stdout.Write(jsonBytes) 164 os.Stdout.WriteString("\n") 165 166 return nil 167 }