Created
March 25, 2013 18:41
-
-
Save inhies/5239492 to your computer and use it in GitHub Desktop.
Generates the important bits of a cjdns configuration file and outputs it as JSON.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"code.google.com/p/go.crypto/curve25519" | |
"crypto/rand" | |
"crypto/sha512" | |
"encoding/json" | |
"fmt" | |
mathrand "math/rand" | |
"runtime" | |
"strconv" | |
"time" | |
) | |
const ( | |
jsonSpacer = "\t" // Character(s) to use for indenting JSON output | |
bindIP = "0.0.0.0" // Bind IP address | |
bindPortMin = 10000 // Minimum port to use for the bind field | |
bindPortMax = 19999 // Maximum port to use for the bind field | |
adminBind = "127.0.0.1:11234" // IP and port for the admin interface to bind to | |
version = "2012.03.25.1" // Program version | |
) | |
// How many cores or processing units do you want to use. | |
// The default is all of them for maximum speed.k | |
var useCPUs = runtime.NumCPU() | |
type KeyPair struct { | |
Private [32]byte | |
Public [32]byte | |
IP string | |
} | |
type Output struct { | |
PrivateKey string `json:"privateKey"` | |
PublicKey string `json:"publicKey"` | |
IPv6 string `json:"ipv6"` | |
Bind string `json:"bind"` | |
Admin adminBlock `json:"admin"` | |
} | |
type adminBlock struct { | |
Password string `json:"password"` | |
Bind string `json:"bind"` | |
} | |
func init() { | |
runtime.GOMAXPROCS(useCPUs) | |
mathrand.Seed(time.Now().UTC().UnixNano()) | |
} | |
func main() { | |
data := MakeKeyPair() | |
output := &Output{} | |
output.PrivateKey = fmt.Sprintf("%x", data.Private[:]) | |
output.PublicKey = string(EncodePubKey(data.Public[:])) + ".k" | |
output.IPv6 = data.IP | |
output.Admin.Password = randString(15, 50) | |
output.Admin.Bind = adminBind | |
output.Bind = bindIP + ":" + strconv.Itoa(bindPortMin+mathrand.Intn(bindPortMax-bindPortMin)) | |
jsonout, err := json.MarshalIndent(output, "", jsonSpacer) | |
if err != nil { | |
fmt.Println(err) | |
return | |
} | |
fmt.Println(string(jsonout)) | |
} | |
// Returns a random alphanumeric string where length is <= max >= min | |
func randString(min, max int) string { | |
r := myRand(min, max, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") | |
return r | |
} | |
// Returns a random character from the specified string where length is <= max >= min | |
func myRand(min, max int, char string) string { | |
var length int | |
if min < max { | |
length = min + mathrand.Intn(max-min) | |
} else { | |
length = min | |
} | |
buf := make([]byte, length) | |
for i := 0; i < length; i++ { | |
buf[i] = char[mathrand.Intn(len(char)-1)] | |
} | |
return string(buf) | |
} | |
// base32 encodes the public key for use in the decoder | |
func EncodePubKey(in []byte) (out []byte) { | |
var wide, bits uint | |
var i2b = []byte("0123456789bcdfghjklmnpqrstuvwxyz") | |
for len(in) > 0 { | |
// Add the 8 bits of data from the next `in` byte above the existing bits | |
wide, in, bits = wide|uint(in[0])<<bits, in[1:], bits+8 | |
for bits > 5 { | |
// Remove the least significant 5 bits and add their character to out | |
wide, out, bits = wide>>5, append(out, i2b[int(wide&0x1F)]), bits-5 | |
} | |
} | |
// If it wasn't a precise multiple of 40 bits, add some padding based on the remaining bits | |
if bits > 0 { | |
out = append(out, i2b[int(wide)]) | |
} | |
return out | |
} | |
// Will loop until a valid keypair is found | |
func MakeKeyPair() (key KeyPair) { | |
random := key.Private[:] | |
Start: | |
rand.Read(random) | |
key.Private[0] &= 248 | |
key.Private[31] &= 127 | |
key.Private[31] |= 64 | |
curve25519.ScalarBaseMult(&key.Public, &key.Private) | |
// Do the hashing that generates the IP | |
out := sha512hash(sha512hash(key.Public[:])) | |
if out[0] != 0xfc { | |
goto Start | |
} | |
// Assemble the IP | |
out = out[0:16] | |
for i := 0; i < 16; i++ { | |
if i > 0 && i < 16 && i%2 == 0 { | |
key.IP += ":" | |
} | |
key.IP += fmt.Sprintf("%02x", out[i]) | |
} | |
return | |
} | |
func sha512hash(input []byte) []byte { | |
h := sha512.New() | |
h.Write(input) | |
return []byte(h.Sum(nil)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment