func StoreCredWithAuthor(cred *credence.Cred, author models.User) (bool, string) { credBytes, _ := proto.Marshal(cred) db := models.DB() var credRecord models.CredRecord credHash := CredHash(cred) db.FirstOrInit(&credRecord, models.CredRecord{CredHash: credHash}) newCred := db.NewRecord(credRecord) if newCred { credRecord.Author = author credRecord.StatementHash = StatementHash(cred) credRecord.CredBytes = credBytes credRecord.SourceUri = cred.SourceUri credRecord.ReceivedAt = time.Now() credRecord.NoComment = cred.Assertion == credence.Cred_NO_COMMENT credRecord.IsTrue = cred.Assertion == credence.Cred_IS_TRUE credRecord.IsFalse = cred.Assertion == credence.Cred_IS_FALSE credRecord.IsAmbiguous = cred.Assertion == credence.Cred_IS_AMBIGUOUS db.Save(&credRecord) } return newCred, credHash }
func StatementAlreadyMade(cred *credence.Cred, user models.User) bool { db := models.DB() var credRecord models.CredRecord db.First(&credRecord, models.CredRecord{ StatementHash: StatementHash(cred), AuthorID: user.ID, }) return !db.NewRecord(credRecord) }
func StartBroadcaster(wg sync.WaitGroup) { defer wg.Done() db := models.DB() msgBytes := make([]byte, 524288) // 0.5 Mb for { _, err := receiver.Read(msgBytes) if err != nil { log.Print(err) continue } hash, err := openssl.SHA1(msgBytes) if err != nil { panic(err) } messageHash := hex.EncodeToString(hash[:]) log.Println("Checking message", messageHash) var previouslySent models.SentMessage db.Where("message_hash = ? AND sent_at > ?", messageHash, time.Now().Add(-5*time.Minute)).First(&previouslySent) if db.NewRecord(previouslySent.MessageHash) { log.Println("Broadcasting message", messageHash) _, err = broadcaster.Write(msgBytes) if err != nil { panic(err) } log.Println("Pitching message", messageHash) _, err = pitcher.Write(msgBytes) if err != nil { panic(err) } previouslySent.SentAt = time.Now() previouslySent.MessageHash = messageHash db.Save(&previouslySent) } else { log.Println("Message already sent recently", messageHash) } } }
func ConnectToPeers(broadcatchers bool, callback func(string) error) { db := models.DB() peers, _ := db.Model(models.Peer{}).Rows() for peers.Next() { var ( peerUri string isBroadcatcher bool ) peers.Scan(&peerUri, &isBroadcatcher) if broadcatchers == isBroadcatcher { // TODO: Catch error _ = callback(peerUri) } } }
func SavePublicKeyToDB(privateKey openssl.PrivateKey) { publicDerBlock, err := privateKey.MarshalPKIXPublicKeyDER() if err != nil { panic(err) } fingerprint, err := openssl.SHA256(publicDerBlock) if err != nil { panic(err) } me := models.Me() me.PublicKey = publicDerBlock me.Fingerprint = fingerprint[:] db := models.DB() db.Save(&me) log.Print("Stored self public key in user DB") }
// TODO: Allow addition of broadcatchers too func ConnectHandler(w http.ResponseWriter, r *http.Request) { switch r.Method { case "POST": uris := r.URL.Query()["uri"] for _, uri := range uris { err := receive.ConnectToBroadcaster(uri) if err == nil { db := models.DB() db.FirstOrCreate(new(models.Peer), models.Peer{Server: uri, IsBroadcatcher: false}) } else { w.WriteHeader(http.StatusBadRequest) return } } w.WriteHeader(http.StatusOK) default: w.WriteHeader(http.StatusMethodNotAllowed) } }
func UserDetailHandler(w http.ResponseWriter, r *http.Request) { // TODO: This is a hack, need proper routing userParam := r.URL.Path[7:] userId, err := strconv.ParseUint(userParam, 10, 64) if err != nil { w.WriteHeader(http.StatusBadRequest) return } db := models.DB() user := &models.User{} db.Where(&models.User{ID: uint(userId)}).First(user) if db.NewRecord(user) { w.WriteHeader(http.StatusNotFound) return } identityAssertion := helpers.AssertIdentity(user) helpers.ModelNegotiator().Negotiate(w, r, identityAssertion) }
// Returns the author of the cred, if it can be determined. // Will return an error if the public key for the author_fingerprint // doesn't match the signature. func DetectAuthor(cred *credence.Cred) (models.User, error) { author := models.User{} db := models.DB() if cred.AuthorFingerprint == nil { users := []models.User{} db.Where("public_key IS NOT NULL").Find(&users) sigCredByte := SignableCredBytes(cred) for _, user := range users { publicKey, err := openssl.LoadPublicKeyFromPEM(user.PublicKey) if err == nil { verifyErr := publicKey.VerifyPKCS1v15(openssl.SHA256_Method, sigCredByte, cred.Signature) if verifyErr == nil { author = user break } } } } else { db.Where("fingerprint = ?", hex.EncodeToString(cred.AuthorFingerprint)).First(&author) if !db.NewRecord(author) { sigCredByte := SignableCredBytes(cred) publicKey, err := openssl.LoadPublicKeyFromPEM(author.PublicKey) if err == nil { verifyErr := publicKey.VerifyPKCS1v15(openssl.SHA256_Method, sigCredByte, cred.Signature) if verifyErr != nil { return models.User{}, verifyErr } } // TODO: What if we can't load the public key? } } return author, nil }
func CredRecordFromCredHash(credHash string) (models.CredRecord, bool) { db := models.DB() credRecord := &models.CredRecord{} db.Where("cred_hash = ?", credHash).Preload("Author").First(credRecord) return *credRecord, !db.NewRecord(credRecord) }