2021-11-09 23:47:33 +00:00
package encryptedstorage
import (
"crypto/rand"
app2 "cwtch.im/cwtch/app"
"cwtch.im/cwtch/app/utils"
"cwtch.im/cwtch/model"
"cwtch.im/cwtch/model/constants"
"cwtch.im/cwtch/peer"
"encoding/base64"
"fmt"
"git.openprivacy.ca/openprivacy/connectivity/tor"
"git.openprivacy.ca/openprivacy/log"
mrand "math/rand"
"os"
"path"
"path/filepath"
"testing"
"time"
)
func TestEncryptedStorage ( t * testing . T ) {
2021-11-10 22:28:52 +00:00
log . SetLevel ( log . LevelDebug )
2021-11-09 23:47:33 +00:00
os . Mkdir ( "tordir" , 0700 )
dataDir := filepath . Join ( "tordir" , "tor" )
os . MkdirAll ( dataDir , 0700 )
// we don't need real randomness for the port, just to avoid a possible conflict...
mrand . Seed ( int64 ( time . Now ( ) . Nanosecond ( ) ) )
socksPort := mrand . Intn ( 1000 ) + 9051
controlPort := mrand . Intn ( 1000 ) + 9052
// generate a random password
key := make ( [ ] byte , 64 )
_ , err := rand . Read ( key )
if err != nil {
panic ( err )
}
tor . NewTorrc ( ) . WithSocksPort ( socksPort ) . WithOnionTrafficOnly ( ) . WithHashedPassword ( base64 . StdEncoding . EncodeToString ( key ) ) . WithControlPort ( controlPort ) . Build ( "tordir/tor/torrc" )
acn , err := tor . NewTorACNWithAuth ( "./tordir" , path . Join ( ".." , ".." , "tor" ) , controlPort , tor . HashedPasswordAuthenticator { Password : base64 . StdEncoding . EncodeToString ( key ) } )
if err != nil {
t . Fatalf ( "Could not start Tor: %v" , err )
}
cwtchDir := path . Join ( "." , "encrypted_storage_profiles" )
os . RemoveAll ( cwtchDir )
os . Mkdir ( cwtchDir , 0700 )
fmt . Println ( "Creating Alice..." )
defer acn . Close ( )
acn . WaitTillBootstrapped ( )
app := app2 . NewApp ( acn , cwtchDir )
app . CreateTaggedPeer ( "alice" , "password" , constants . ProfileTypeV1Password )
app . CreateTaggedPeer ( "bob" , "password" , constants . ProfileTypeV1Password )
alice := utils . WaitGetPeer ( app , "alice" )
bob := utils . WaitGetPeer ( app , "bob" )
alice . Listen ( )
bob . Listen ( )
// To keep this large test organized, we will break it down into sub tests...
subTestAliceAddAndDeleteBob ( t , alice , bob )
2021-11-10 22:28:52 +00:00
conversations , err := alice . FetchConversations ( )
if err != nil || len ( conversations ) != 1 {
t . Fatalf ( "unexpected issue when fetching all of alices conversations. Expected 1 got : %v %v" , conversations , err )
}
2021-11-09 23:47:33 +00:00
alice . PeerWithOnion ( bob . GetOnion ( ) )
time . Sleep ( time . Second * 30 )
2021-11-11 00:41:43 +00:00
alice . SendMessage ( 2 , "Hello Bob" )
2021-11-16 23:06:30 +00:00
if err != nil {
t . Fatalf ( "alice should have been able to fetch her own message" )
}
_ , attr , err := alice . GetChannelMessage ( 2 , 0 , 1 )
if attr [ constants . AttrAck ] != "false" {
t . Fatalf ( "Alices message should have been acknowledged...yet" )
}
2021-11-09 23:47:33 +00:00
time . Sleep ( time . Second * 30 )
2021-11-10 22:28:52 +00:00
ci , _ := bob . FetchConversationInfo ( alice . GetOnion ( ) )
2021-11-09 23:47:33 +00:00
body , _ , err := bob . GetChannelMessage ( ci . ID , 0 , 1 )
if body != "Hello Bob" || err != nil {
t . Fatalf ( "unexpected message in conversation channel %v %v" , body , err )
} else {
t . Logf ( "succesfully found message in conversation channel %v" , body )
}
2021-11-16 23:06:30 +00:00
// Check that we received an ACk...
_ , attr , err = alice . GetChannelMessage ( 2 , 0 , 1 )
if err != nil {
t . Fatalf ( "alice should have been able to fetch her own message" )
}
if attr [ constants . AttrAck ] != "true" {
t . Fatalf ( "Alices message should have been acknowledged." )
}
2021-11-09 23:47:33 +00:00
}
// Sub Test testing that Alice can add Bob, delete the conversation associated with Bob, and then add Bob again
// Under a different conversation identifier.
func subTestAliceAddAndDeleteBob ( t * testing . T , alice peer . CwtchPeer , bob peer . CwtchPeer ) {
t . Logf ( "Starting Sub Test AliceAddAndDeleteBob" )
alice . NewContactConversation ( bob . GetOnion ( ) , model . AccessControl { Read : true , Append : true , Blocked : false } , true )
// Test Basic Fetching
bobCI , err := alice . FetchConversationInfo ( bob . GetOnion ( ) )
if bobCI == nil || err != nil {
t . Fatalf ( "alice should have been able to fetch bobs conversationf info ci:%v err:%v" , bobCI , err )
} else {
t . Logf ( "Bobs Conversation Info fetched successfully: %v" , bobCI )
}
oldID := bobCI . ID
2021-11-10 22:28:52 +00:00
alice . DeleteConversation ( oldID )
2021-11-09 23:47:33 +00:00
// Test Basic Fetching
bobCI , err = alice . FetchConversationInfo ( bob . GetOnion ( ) )
if bobCI != nil {
t . Fatalf ( "alice should **not** have been able to fetch bobs conversationf info ci:%v err:%v" , bobCI , err )
} else {
t . Logf ( "expected error fetching deleted conversation info: %v" , err )
}
alice . NewContactConversation ( bob . GetOnion ( ) , model . AccessControl { Read : true , Append : true , Blocked : false } , true )
// Test Basic Fetching
bobCI , err = alice . FetchConversationInfo ( bob . GetOnion ( ) )
if bobCI == nil || err != nil {
t . Fatalf ( "alice should have been able to fetch bobs conversationf info ci:%v err:%v" , bobCI , err )
} else {
t . Logf ( "Bobs Conversation Info fetched successfully: %v" , bobCI )
}
if oldID == bobCI . ID {
t . Fatalf ( "bob should have a different conversation ID. Instead it is the same as the old conversation id, meaning something has gone wrong in the storage engine." )
}
}