func TestBasic(t *testing.T) { var priv, pub [32]byte rand.Read(priv[:]) curve25519.ScalarBaseMult(&pub, &priv) var d Descriptor d.Nickname = "mylittletorry18" d.Contact = "TvdW" d.Platform = "Tor 0.2.6.2-alpha on MS-DOS" d.Address = net.ParseIP("80.57.124.58") d.ORPort = 1234 d.UptimeStart = time.Now() d.NTORKey = pub[:] d.BandwidthAvg = 1000000 d.BandwidthBurst = 1200000 d.BandwidthObserved = 30107 k, err := openssl.GenerateRSAKeyWithExponent(1024, 65537) if err != nil { t.Error(err) } d.OnionKey, err = openssl.GenerateRSAKeyWithExponent(1024, 65537) d.SigningKey = k desc, err := d.SignedDescriptor() if err != nil { t.Error(err) } log.Println(desc) }
func NewTLSCtx(isClient bool, or *ORCtx) (*TorTLS, error) { log.Printf("Creating TLS context with isClient=%v\n", isClient) sslCtx, err := openssl.NewCtxWithVersion(openssl.AnyVersion) if err != nil { return nil, err } tls := &TorTLS{ ctx: sslCtx, } // Considering how important this piece of code is for resisting fingerprints, we just follow whatever Tor itself does if !isClient { // XXX simplify nickname1 := RandomHostname(8, 20, "www.", ".net") nickname2 := RandomHostname(8, 20, "www.", ".com") issued, _ := time.ParseDuration("-24h") // XXX check what tor does (some time ago, then a long-time cert) expires, _ := time.ParseDuration("24h") // XXX also, don't re-use for all certs tmpPk, err := openssl.GenerateRSAKeyWithExponent(1024, 65537) if err != nil { return nil, err } authPk, err := openssl.GenerateRSAKeyWithExponent(1024, 65537) if err != nil { return nil, err } cert, err := openssl.NewCertificate(&openssl.CertificateInfo{ CommonName: nickname1, Serial: rand.Int63(), Issued: issued, Expires: expires, }, tmpPk) if err != nil { return nil, err } identityPk := or.identityKey idcert, err := openssl.NewCertificate(&openssl.CertificateInfo{ CommonName: nickname2, Serial: rand.Int63(), Issued: issued, Expires: expires, }, identityPk) if err != nil { return nil, err } authcert, err := openssl.NewCertificate(&openssl.CertificateInfo{ CommonName: nickname1, Serial: rand.Int63(), Issued: issued, Expires: expires, }, authPk) if err != nil { return nil, err } if err := cert.SetIssuer(idcert); err != nil { return nil, err } if err := cert.Sign(identityPk, openssl.EVP_SHA1); err != nil { return nil, err } if err := idcert.SetIssuer(idcert); err != nil { return nil, err } if err := idcert.Sign(identityPk, openssl.EVP_SHA1); err != nil { return nil, err } if err := authcert.SetIssuer(idcert); err != nil { return nil, err } if err := authcert.Sign(identityPk, openssl.EVP_SHA1); err != nil { return nil, err } sslCtx.UseCertificate(cert) sslCtx.UsePrivateKey(tmpPk) sslCtx.SetEllipticCurve(openssl.Prime256v1) tls.LinkCert = cert tls.LinkKey = tmpPk tls.LinkCertDER, err = cert.MarshalDER() if err != nil { return nil, err } tls.IdCert = idcert tls.IdKey = identityPk tls.IdCertDER, err = idcert.MarshalDER() if err != nil { return nil, err } keyDer, _ := identityPk.MarshalPKCS1PublicKeyDER() fingerprint := sha1.Sum(keyDer) log.Printf("Our fingerprint is %X\n", fingerprint) copy(tls.Fingerprint[:], fingerprint[:]) { sha := sha256.New() sha.Write(keyDer) tls.Fingerprint256 = sha.Sum(nil) } tls.AuthCert = authcert tls.AuthKey = authPk tls.AuthCertDER, err = authcert.MarshalDER() if err != nil { return nil, err } } // We don't want SSLv2 or SSLv3 sslCtx.SetOptions(openssl.NoSSLv2 | openssl.NoSSLv3) // Prefer the server's ordering of ciphers: the client's ordering has // historically been chosen for fingerprinting resistance. sslCtx.SetOptions(openssl.CipherServerPreference) //XXX: panic() if we don't have openssl of 1.0.1e or later //XXX: please remember me why... // Tickets hurt perfect forward secrecy, but we still have non-server clients announce them, to reduce fingerprinting impact if !isClient { sslCtx.SetOptions(openssl.NoTicket) } // This saves us quite some memory //sslCtx.SetMode(openssl.ReleaseBuffers) // Avoid reusing DH keys if we don't have to sslCtx.SetOptions(openssl.SingleDHUse | openssl.SingleECDHUse) // Never renegotiate. sslCtx.SetOptions(openssl.NoSessionResumptionOrRenegotiation) // All compression does with encrypted data is waste CPU cycles. Disable it sslCtx.SetOptions(openssl.NoCompression) // Disable session caching sslCtx.SetSessionCacheMode(openssl.SessionCacheOff) // Allow all peer certificates sslCtx.SetVerify(openssl.VerifyNone, nil) return tls, nil }
func NewOR(torConf *Config) (*ORCtx, error) { connStr := fmt.Sprintf(":%d", torConf.ORPort) listener, err := net.Listen("tcp", connStr) if err != nil { return nil, err } ctx := &ORCtx{ listener: listener, authenticatedConnections: make(map[Fingerprint]*OnionConnection), config: torConf, } if _, err := os.Stat(torConf.DataDirectory + "/keys/secret_id_key"); os.IsNotExist(err) { Log(LOG_INFO, "Generating new keys") os.Mkdir(torConf.DataDirectory, 0755) os.Mkdir(torConf.DataDirectory+"/keys", 0700) { newIDKey, err := openssl.GenerateRSAKeyWithExponent(1024, 65537) if err != nil { return nil, err } newIDKeyPEM, err := newIDKey.MarshalPKCS1PrivateKeyPEM() if err != nil { return nil, err } if err := ioutil.WriteFile(torConf.DataDirectory+"/keys/secret_id_key", newIDKeyPEM, 0600); err != nil { return nil, err } } { newOnionKey, err := openssl.GenerateRSAKeyWithExponent(1024, 65537) if err != nil { return nil, err } newOnionKeyPEM, err := newOnionKey.MarshalPKCS1PrivateKeyPEM() if err != nil { return nil, err } if err := ioutil.WriteFile(torConf.DataDirectory+"/keys/secret_onion_key", newOnionKeyPEM, 0600); err != nil { return nil, err } } { var curveDataPriv [32]byte var curveDataPub [32]byte CRandBytes(curveDataPriv[0:32]) curveDataPriv[0] &= 248 curveDataPriv[31] &= 127 curveDataPriv[31] |= 64 curve25519.ScalarBaseMult(&curveDataPub, &curveDataPriv) var buf bytes.Buffer buf.WriteString("== c25519v1: onion ==") for i := buf.Len(); i < 32; i++ { buf.Write([]byte{0}) } buf.Write(curveDataPriv[:]) buf.Write(curveDataPub[:]) if err := ioutil.WriteFile(torConf.DataDirectory+"/keys/secret_onion_key_ntor", buf.Bytes(), 0600); err != nil { return nil, err } } } { identityPem, err := ioutil.ReadFile(torConf.DataDirectory + "/keys/secret_id_key") if err != nil { return nil, err } identityPk, err := openssl.LoadPrivateKeyFromPEM(identityPem) if err != nil { return nil, err } ctx.identityKey = identityPk } { onionPem, err := ioutil.ReadFile(torConf.DataDirectory + "/keys/secret_onion_key") if err != nil { return nil, err } onionPk, err := openssl.LoadPrivateKeyFromPEM(onionPem) if err != nil { return nil, err } ctx.onionKey = onionPk } { ntorData, err := ioutil.ReadFile(torConf.DataDirectory + "/keys/secret_onion_key_ntor") if err != nil { return nil, err } if len(ntorData) != 96 { return nil, errors.New("ntor data corrupt") } copy(ctx.ntorPrivate[:], ntorData[32:64]) copy(ctx.ntorPublic[:], ntorData[64:96]) } if err := SetupTLS(ctx); err != nil { return nil, err } ctx.descriptor.UptimeStart = time.Now() return ctx, nil }