func (s *XLSuite) makeHostAndKeys(c *C, rng *xr.PRNG) ( n *xn.Node, ckPriv, skPriv *rsa.PrivateKey) { // XXX names may not be unique name := rng.NextFileName(6) for { first := string(name[0]) if !strings.Contains(first, "0123456789") && !strings.Contains(name, "-") { break } name = rng.NextFileName(6) } id := s.makeANodeID(c, rng) lfs := "tmp/" + hex.EncodeToString(id.Value()) ckPriv = s.makeAnRSAKey(c) skPriv = s.makeAnRSAKey(c) n, err2 := xn.New(name, id, lfs, ckPriv, skPriv, nil, nil, nil) c.Assert(err2, IsNil) c.Assert(n, Not(IsNil)) c.Assert(name, Equals, n.GetName()) actualID := n.GetNodeID() c.Assert(true, Equals, id.Equal(actualID)) // s.doKeyTests(c, n, rng) c.Assert(0, Equals, (*n).SizePeers()) c.Assert(0, Equals, (*n).SizeOverlays()) c.Assert(0, Equals, n.SizeConnections()) c.Assert(lfs, Equals, n.GetLFS()) return n, ckPriv, skPriv }
func NewUserMember( name, lfs string, ckPriv, skPriv *rsa.PrivateKey, serverName string, serverID *xi.NodeID, serverEnd xt.EndPointI, serverCK, serverSK *rsa.PublicKey, clusterName string, clusterAttrs uint64, clusterID *xi.NodeID, size, epCount uint32, e []xt.EndPointI) (ac *UserMember, err error) { var attrs uint64 nodeID, err := xi.New(nil) if err == nil { if lfs == "" { attrs |= xcl.ATTR_EPHEMERAL } node, err := xn.New(name, nodeID, lfs, ckPriv, skPriv, nil, nil, nil) if err == nil { mn, err := NewMemberMaker(node, attrs, serverName, serverID, serverEnd, serverCK, serverSK, // *rsa.PublicKey, clusterName, clusterAttrs, clusterID, size, epCount, e) if err == nil { // Start() fills in clusterID ac = &UserMember{ MemberMaker: *mn, } } } } return }
func NewMockUpaxClient(name, lfs string, members []*xcl.MemberInfo, primary uint) (mc *MockUpaxClient, err error) { var ( ckPriv, skPriv *rsa.PrivateKey ep []xt.EndPointI node *xn.Node uc *UpaxClient ) // lfs should be a well-formed POSIX path; if the directory does // not exist we should create it. err = xf.CheckLFS(lfs, 0750) // The ckPriv is an RSA key used to encrypt short messages. if err == nil { if ckPriv == nil { ckPriv, err = rsa.GenerateKey(rand.Reader, 2048) } if err == nil { // The skPriv is an RSA key used to create digital signatures. if skPriv == nil { skPriv, err = rsa.GenerateKey(rand.Reader, 2048) } } } // The mock client uses a system-assigned endpoint if err == nil { var endPoint *xt.TcpEndPoint endPoint, err = xt.NewTcpEndPoint("127.0.0.1:0") if err == nil { ep = []xt.EndPointI{endPoint} } } // spin up an XLattice node if err == nil { node, err = xn.New(name, nil, // get a default NodeID lfs, ckPriv, skPriv, nil, ep, nil) // nil overlays, peers } if err == nil { uc, err = NewUpaxClient(ckPriv, skPriv, node, members, primary) if err == nil { mc = &MockUpaxClient{ UpaxClient: *uc, } } } return }
func New(name string, id *xi.NodeID, lfs string, commsKey, sigKey *rsa.PrivateKey, o []xo.OverlayI, e []xt.EndPointI, p []*xn.Peer) ( uNode *UpaxNode, err error) { n, err := xn.New(name, id, lfs, commsKey, sigKey, o, e, p) if err == nil { uNode = &UpaxNode{ ckPriv: commsKey, skPriv: sigKey, Node: *n, } } return }
func (s *XLSuite) TestCrytpo(c *C) { if VERBOSITY > 0 { fmt.Println("TEST_CRYPTO") } rng := xr.MakeSimpleRNG() nodeID := s.makeANodeID(c, rng) ckPriv := s.makeAnRSAKey(c) skPriv := s.makeAnRSAKey(c) node, err := xn.New("foo", nodeID, "", ckPriv, skPriv, nil, nil, nil) c.Assert(err, IsNil) c.Assert(node, Not(IsNil)) ck := node.GetCommsPublicKey() // XXX ADDING 4 BYTE VERSION NUMBER // Generate 16-byte AES IV, 32-byte AES key, and 8-byte salt // and 4-byte version number for the Hello and another 20 bytes as salt // for the OAEP encrypt. For testing purposes these need not be crypto // grade. salty := make([]byte, 3*aes.BlockSize+8+4+xu.SHA1_BIN_LEN) rng.NextBytes(salty) iv1 := salty[:aes.BlockSize] key1 := salty[aes.BlockSize : 3*aes.BlockSize] salt1 := salty[3*aes.BlockSize : 3*aes.BlockSize+8] vBytes := salty[3*aes.BlockSize+8 : 3*aes.BlockSize+12] version1 := uint32( (0xff & vBytes[3] << 24) | (0xff & vBytes[2] << 16) | (0xff & vBytes[1] << 8) | (0xff & vBytes[0])) _ = version1 // DEBUG oaep1 := salty[3*aes.BlockSize+12:] oaepSalt := bytes.NewBuffer(oaep1) // == HELLO ===================================================== // On the client side: // Create and marshal a hello containing AES iv1, key1, salt1, version1. // // There is no reason at all to use protobufs for this purpose. // Just encrypt iv1 + key1 + salt1 + version1 sha := sha1.New() data := salty[:3*aes.BlockSize+8+4] // contains iv1,key1,salt1,version1 c.Assert(len(data), Equals, 60) ciphertext, err := rsa.EncryptOAEP(sha, oaepSalt, ck, data, nil) c.Assert(err, IsNil) c.Assert(ciphertext, Not(IsNil)) // On the server side: ------------------------------------------ // decrypt the hello using the node's private comms key plaintext, err := rsa.DecryptOAEP(sha, nil, ckPriv, ciphertext, nil) c.Assert(err, IsNil) c.Assert(plaintext, Not(IsNil)) // verify that iv1, key1, salt1, version1 are the same c.Assert(data, DeepEquals, plaintext) // == HELLO REPLY =============================================== // On the server side: // // Create, marshal a reply containing iv2, key2, salt2, salt1, version2 // This could be done as a Protobuf message, but is handled as a simple // byte slice instead. // create the session iv + key plus salt2 reply := make([]byte, 3*aes.BlockSize+8) rng.NextBytes(reply) iv2 := reply[:aes.BlockSize] key2 := reply[aes.BlockSize : 3*aes.BlockSize] salt2 := reply[3*aes.BlockSize] reply = append(reply, salt1...) reply = append(reply, vBytes...) // We need padding because the message is not or may not be an // integer multiple of the block size. paddedReply, err := xc.AddPKCS7Padding(reply, aes.BlockSize) c.Assert(err, IsNil) c.Assert(paddedReply, Not(IsNil)) // encrypt the reply using engine1a = iv1, key1 engine1a, err := aes.NewCipher(key1) // on server c.Assert(err, IsNil) c.Assert(engine1a, Not(IsNil)) aesEncrypter1a := cipher.NewCBCEncrypter(engine1a, iv1) c.Assert(err, IsNil) c.Assert(aesEncrypter1a, Not(IsNil)) // we require that the message size be a multiple of the block size c.Assert(aesEncrypter1a.BlockSize(), Equals, aes.BlockSize) msgLen := len(paddedReply) nBlocks := (msgLen + aes.BlockSize - 1) / aes.BlockSize c.Assert(msgLen, Equals, nBlocks*aes.BlockSize) ciphertext = make([]byte, nBlocks*aes.BlockSize) aesEncrypter1a.CryptBlocks(ciphertext, paddedReply) // dest <- src // On the client side: ------------------------------------------ // decrypt the reply using engine1b = iv1, key1 engine1b, err := aes.NewCipher(key1) // on client c.Assert(err, IsNil) c.Assert(engine1b, Not(IsNil)) aesDecrypter1b := cipher.NewCBCDecrypter(engine1b, iv1) c.Assert(err, IsNil) c.Assert(aesDecrypter1b, Not(IsNil)) plaintext = make([]byte, nBlocks*aes.BlockSize) aesDecrypter1b.CryptBlocks(plaintext, ciphertext) // dest <- src c.Assert(plaintext, DeepEquals, paddedReply) unpaddedReply, err := xc.StripPKCS7Padding(paddedReply, aes.BlockSize) c.Assert(err, IsNil) c.Assert(unpaddedReply, DeepEquals, reply) _ = salt2 // WE DON'T USE THIS YET // AES HANDLING FOR ALL FURTHER MESSAGES ======================== // -- CLIENT-SIDE AES SETUP ----------------- // encrypt the client msg using engineC = iv2, key2 engineC, err := aes.NewCipher(key2) c.Assert(err, IsNil) c.Assert(engineC, Not(IsNil)) encrypterC := cipher.NewCBCEncrypter(engineC, iv2) c.Assert(err, IsNil) c.Assert(encrypterC, Not(IsNil)) decrypterC := cipher.NewCBCDecrypter(engineC, iv2) c.Assert(err, IsNil) c.Assert(decrypterC, Not(IsNil)) // we require that the message size be a multiple of the block size c.Assert(encrypterC.BlockSize(), Equals, aes.BlockSize) c.Assert(decrypterC.BlockSize(), Equals, aes.BlockSize) // -- SERVER-SIDE AES SETUP ----------------- engineS, err := aes.NewCipher(key2) c.Assert(err, IsNil) c.Assert(engineS, Not(IsNil)) encrypterS := cipher.NewCBCEncrypter(engineS, iv2) c.Assert(err, IsNil) c.Assert(encrypterS, Not(IsNil)) decrypterS := cipher.NewCBCDecrypter(engineS, iv2) c.Assert(err, IsNil) c.Assert(decrypterS, Not(IsNil)) // we require that the message size be a multiple of the block size c.Assert(encrypterS.BlockSize(), Equals, aes.BlockSize) c.Assert(decrypterS.BlockSize(), Equals, aes.BlockSize) //// == CLIENT MSG ================================================ //// On the client side: //// create and marshal client name, specs, salt2, digsig over that //clientName := rng.NextFileName(8) //// create and marshal a token containing attrs, id, ck, sk, myEnd* //attrs := uint64(947) //ckBytes, err := xc.RSAPrivateKeyToWire(ckPriv) //c.Assert(err, IsNil) //skBytes, err := xc.RSAPrivateKeyToWire(skPriv) //c.Assert(err, IsNil) //myEnd := []string{"127.0.0.1:4321"} //token := &XLRegMsg_Token{ // Attrs: &attrs, // ID: nodeID.Value(), // CommsKey: ckBytes, // SigKey: skBytes, // MyEnd: myEnd, //} //op := XLRegMsg_Client //clientMsg := XLRegMsg{ // Op: &op, // ClientName: &clientName, // ClientSpecs: token, //} //ciphertext, err = EncodePadEncrypt(&clientMsg, encrypterC) //c.Assert(err, IsNil) //// On the server side: ------------------------------------------ //clientMsg2, err := DecryptUnpadDecode(ciphertext, decrypterS) //c.Assert(err, IsNil) //c.Assert(clientMsg2.GetOp(), Equals, XLRegMsg_Client) //// verify that id, ck, sk, myEnd* survive the trip unchanged //name2 := clientMsg2.GetClientName() //c.Assert(name2, Equals, clientName) //clientSpecs2 := clientMsg2.GetClientSpecs() //c.Assert(clientSpecs2, Not(IsNil)) //attrs2 := clientSpecs2.GetAttrs() //id2 := clientSpecs2.GetID() //ckBytes2 := clientSpecs2.GetCommsKey() //skBytes2 := clientSpecs2.GetSigKey() //myEnd2 := clientSpecs2.GetMyEnd() // a string array //c.Assert(attrs2, Equals, attrs) //c.Assert(id2, DeepEquals, nodeID.Value()) //c.Assert(ckBytes2, DeepEquals, ckBytes) //c.Assert(skBytes2, DeepEquals, skBytes) //c.Assert(myEnd2, DeepEquals, myEnd) //// == CLIENT OK ================================================= //// on the server side: //clientID := s.makeAnID(c, rng) //attrsBack := uint64(479) //op = XLRegMsg_ClientOK //clientOKMsg := XLRegMsg{ // Op: &op, // ClientID: clientID, // Attrs: &attrsBack, //} //ciphertext, err = EncodePadEncrypt(&clientOKMsg, encrypterS) //c.Assert(err, IsNil) //// on the client side ------------------------------------------- //clientOK2, err := DecryptUnpadDecode(ciphertext, decrypterC) //c.Assert(err, IsNil) //c.Assert(clientOK2.GetOp(), Equals, XLRegMsg_ClientOK) //clientID2 := clientOK2.GetClientID() //c.Assert(clientID2, DeepEquals, clientID) //attrsBack2 := clientOK2.GetAttrs() //c.Assert(attrsBack2, Equals, attrsBack) //// == CREATE ==================================================== //// on the client side: //clusterName := rng.NextFileName(8) //clusterSize := uint32(2 + rng.Intn(60)) //op = XLRegMsg_Create //createMsg := XLRegMsg{ // Op: &op, // ClusterName: &clusterName, // ClusterSize: &clusterSize, //} //ciphertext, err = EncodePadEncrypt(&createMsg, encrypterC) //c.Assert(err, IsNil) //// on the server side ------------------------------------------- //createMsg2, err := DecryptUnpadDecode(ciphertext, decrypterS) //c.Assert(err, IsNil) //c.Assert(createMsg2.GetOp(), Equals, XLRegMsg_Create) //clusterName2 := createMsg2.GetClusterName() //c.Assert(clusterName2, Equals, clusterName) //clusterSize2 := createMsg2.GetClusterSize() //c.Assert(clusterSize2, Equals, clusterSize) //// == CREATE REPLY ============================================== //// on the server side: //clusterID := s.makeAnID(c, rng) //sizeBack := uint32(2 + rng.Intn(60)) //op = XLRegMsg_CreateReply //createReplyMsg := XLRegMsg{ // Op: &op, // ClusterID: clusterID, // ClusterSize: &sizeBack, //} //ciphertext, err = EncodePadEncrypt(&createReplyMsg, encrypterS) //c.Assert(err, IsNil) //// on the client side ------------------------------------------- //createReply2, err := DecryptUnpadDecode(ciphertext, decrypterC) //c.Assert(err, IsNil) //c.Assert(createReply2.GetOp(), Equals, XLRegMsg_CreateReply) //clusterID2 := createReply2.GetClusterID() //c.Assert(clusterID2, DeepEquals, clusterID) //sizeBack2 := createReply2.GetClusterSize() //c.Assert(sizeBack2, Equals, sizeBack) //// == JOIN ====================================================== //// On the client side: //op = XLRegMsg_Join //joinMsg := XLRegMsg{ // Op: &op, // ClusterID: clusterID, //} //ciphertext, err = EncodePadEncrypt(&joinMsg, encrypterC) //c.Assert(err, IsNil) //// on the server side ------------------------------------------- //join2, err := DecryptUnpadDecode(ciphertext, decrypterS) //c.Assert(err, IsNil) //c.Assert(join2.GetOp(), Equals, XLRegMsg_Join) //clusterID2 = join2.GetClusterID() //c.Assert(clusterID2, DeepEquals, clusterID) // GEEP //// == JOIN REPLY ================================================ //// on the server side: //op = XLRegMsg_JoinReply //joinReplyMsg := XLRegMsg{ // Op: &op, // ClusterID: clusterID, // ClusterSize: &clusterSize, //} //ciphertext, err = EncodePadEncrypt(&joinReplyMsg, encrypterS) //c.Assert(err, IsNil) //// on the client side ------------------------------------------- //joinReply2, err := DecryptUnpadDecode(ciphertext, decrypterC) //c.Assert(err, IsNil) //c.Assert(joinReply2.GetOp(), Equals, XLRegMsg_JoinReply) //clusterID2 = joinReply2.GetClusterID() //c.Assert(clusterID2, DeepEquals, clusterID) //sizeBack = joinReply2.GetClusterSize() //c.Assert(sizeBack, Equals, clusterSize) //// == GET ======================================================= //// On the client side: //// on the server side ------------------------------------------- //// == MEMBERS =================================================== //// On the server side: //// on the client side ------------------------------------------- //// create and marshal a set of 3=5 tokens each containing attrs, //// nodeID, clusterID //// XXX STUB XXX //// encrypt the msg using engineC = iv2, key2 //// XXX STUB XXX //// decrypt the msg using engineS = iv2, key2 //// XXX STUB XXX //// verify that the various tokens (id, ck, sk, myEnd*) survive the //// trip unchanged //// XXX STUB XXX //// == BYE ======================================================= //// On the client side: //op = XLRegMsg_Bye //byeMsg := XLRegMsg{ // Op: &op, //} //ciphertext, err = EncodePadEncrypt(&byeMsg, encrypterC) //c.Assert(err, IsNil) //// on the server side ------------------------------------------- //bye2, err := DecryptUnpadDecode(ciphertext, decrypterS) //c.Assert(err, IsNil) //c.Assert(bye2.GetOp(), Equals, XLRegMsg_Bye) //// == ACK ======================================================= //// on the server side: //op = XLRegMsg_Ack //ackMsg := XLRegMsg{ // Op: &op, //} //ciphertext, err = EncodePadEncrypt(&ackMsg, encrypterS) //c.Assert(err, IsNil) //// on the client side ------------------------------------------- //ack2, err := DecryptUnpadDecode(ciphertext, decrypterC) //c.Assert(err, IsNil) //c.Assert(ack2.GetOp(), Equals, XLRegMsg_Ack) }
func NewEphServer() (ms *EphServer, err error) { // Create an XLattice node with quasi-random parameters including // low-quality keys and an endPoint in 127.0.0.1, localhost. var ( ckPriv, skPriv *rsa.PrivateKey rn *RegNode ep *xt.TcpEndPoint node *xn.Node reg *Registry server *RegServer ) rng := xr.MakeSimpleRNG() name := rng.NextFileName(16) idBuf := make([]byte, xu.SHA1_BIN_LEN) rng.NextBytes(idBuf) lfs := "tmp/" + hex.EncodeToString(idBuf) id, err := xi.New(nil) if err == nil { // XXX cheap keys, too weak for any serious use ckPriv, err = rsa.GenerateKey(rand.Reader, 1024) if err == nil { skPriv, err = rsa.GenerateKey(rand.Reader, 1024) } } if err == nil { ep, err = xt.NewTcpEndPoint("127.0.0.1:0") eps := []xt.EndPointI{ep} if err == nil { node, err = xn.New(name, id, lfs, ckPriv, skPriv, nil, eps, nil) if err == nil { err = node.OpenAcc() // so acceptors are now live if err == nil { rn, err = NewRegNode(node, ckPriv, skPriv) if err == nil { // DEBUG if rn == nil { fmt.Println("regNode is NIL!\n") } else { fmt.Printf("eph server listening on %s\n", rn.GetAcceptor(0).String()) } // END // a registry with no clusters and no logger opt := &RegOptions{ EndPoint: ep, // not used Ephemeral: true, GlobalEndPoint: node.GetEndPoint(0), Lfs: lfs, // redundant (is in node's BaseNode) Logger: nil, K: DEFAULT_K, M: DEFAULT_M, } reg, err = NewRegistry(nil, rn, opt) if err == nil { server, err = NewRegServer(reg, true, 1) if err == nil { ms = &EphServer{ acc: rn.GetAcceptor(0), Server: server, } } } } } } } } return }
func setup(opt *reg.RegOptions) (rs *reg.RegServer, err error) { // If LFS/.xlattice/reg.config exists, we load that. Otherwise we // create a node. In either case we force the node to listen on // the designated port var ( e []xt.EndPointI node *xn.Node pathToConfigFile string rn *reg.RegNode ckPriv, skPriv *rsa.PrivateKey ) logger := opt.Logger verbose := opt.Verbose greetings := fmt.Sprintf("xlReg v%s %s start run\n", reg.VERSION, reg.VERSION_DATE) if verbose { fmt.Print(greetings) } logger.Print(greetings) pathToConfigFile = path.Join(path.Join(opt.Lfs, ".xlattice"), "reg.config") found, err := xf.PathExists(pathToConfigFile) if err == nil { if found { logger.Printf("Loading existing reg config from %s\n", pathToConfigFile) // The registry node already exists. Parse it and we are done. var data []byte data, err = ioutil.ReadFile(pathToConfigFile) if err == nil { rn, _, err = reg.ParseRegNode(string(data)) } } else { logger.Println("No config file found, creating new registry.") // We need to create a registry node from scratch. nodeID, _ := xi.New(nil) ep, err := xt.NewTcpEndPoint(opt.Address + ":" + opt.Port) if err == nil { e = []xt.EndPointI{ep} ckPriv, err = rsa.GenerateKey(rand.Reader, 2048) if err == nil { skPriv, err = rsa.GenerateKey(rand.Reader, 2048) } if err == nil { node, err = xn.New("xlReg", nodeID, opt.Lfs, ckPriv, skPriv, nil, e, nil) if err == nil { node.OpenAcc() // XXX needs a complementary close if err == nil { // DEBUG fmt.Printf("XLattice node successfully created\n") fmt.Printf(" listening on %s\n", ep.String()) // END rn, err = reg.NewRegNode(node, ckPriv, skPriv) if err == nil { // DEBUG fmt.Printf("regNode successfully created\n") // END err = xf.MkdirsToFile(pathToConfigFile, 0700) if err == nil { err = ioutil.WriteFile(pathToConfigFile, []byte(rn.String()), 0400) // DEBUG } else { fmt.Printf("error writing config file: %v\n", err.Error()) } // END -------------- // DEBUG } else { fmt.Printf("error creating regNode: %v\n", err.Error()) // END } } } } } } } if err == nil { var r *reg.Registry r, err = reg.NewRegistry(nil, // nil = clusters so far rn, opt) // regNode, options if err == nil { logger.Printf("Registry name: %s\n", rn.GetName()) logger.Printf(" ID: %s\n", rn.GetNodeID().String()) } if err == nil { var verbosity int if opt.Verbose { verbosity++ } rs, err = reg.NewRegServer(r, opt.Testing, verbosity) } } if err != nil { logger.Printf("ERROR: %s\n", err.Error()) } return }