1719 lines
56 KiB
Go
1719 lines
56 KiB
Go
|
|
// serverResponse provides functions to create and read server responses
|
|
|
|
package serverResponse
|
|
|
|
// See a description of each response and its purpose in Specification.md
|
|
|
|
//TODO: Verify all received values and function inputs
|
|
|
|
import "seekia/internal/cryptography/blake3"
|
|
import "seekia/internal/cryptography/chaPolyShrink"
|
|
import "seekia/internal/cryptography/edwardsKeys"
|
|
import "seekia/internal/cryptography/kyber"
|
|
import "seekia/internal/cryptography/nacl"
|
|
import "seekia/internal/encoding"
|
|
import "seekia/internal/helpers"
|
|
import "seekia/internal/identity"
|
|
import "seekia/internal/messaging/readMessages"
|
|
import "seekia/internal/moderation/readReports"
|
|
import "seekia/internal/moderation/readReviews"
|
|
import "seekia/internal/parameters/readParameters"
|
|
import "seekia/internal/profiles/readProfiles"
|
|
|
|
import messagepack "github.com/vmihailenco/msgpack/v5"
|
|
|
|
import "slices"
|
|
import "crypto/rand"
|
|
import "errors"
|
|
|
|
// The variables below specify the maximum number of items that can fit into a response
|
|
// They are used when making requests to know when to break up the request so it does not exceed the maximum size
|
|
//TODO: Make these numbers accurate
|
|
|
|
const MaximumProfilesInResponse_GetProfilesInfo int = 100000
|
|
const MaximumMessageHashesInResponse_GetMessageHashesList int = 100000
|
|
const MaximumMessagesInResponse_GetMessages int = 100000
|
|
const MaximumReviewHashesInResponse_GetReviewHashesList int = 100000
|
|
const MaximumReviewsInResponse_GetIdentityReviewsInfo int = 100000
|
|
const MaximumReviewsInResponse_GetMessageReviewsInfo int = 100000
|
|
const MaximumReviewsInResponse_GetReviews int = 100000
|
|
const MaximumReportsInResponse_GetIdentityReportsInfo int = 100000
|
|
const MaximumReportsInResponse_GetMessageReportsInfo int = 100000
|
|
const MaximumReportsInResponse_GetReports int = 100000
|
|
const MaximumBalancesInResponse_GetAddressDeposits int = 100000
|
|
const MaximumProfilesInResponse_GetProfileViewableStatuses int = 10000
|
|
const MaximumIdentitiesInResponse_GetIdentityViewableStatuses int = 1000
|
|
|
|
func GetMaximumProfilesInResponse_GetProfiles(profileType string)(int, error){
|
|
|
|
if (profileType == "Mate"){
|
|
return 1000, nil
|
|
}
|
|
if (profileType == "Host"){
|
|
return 10000, nil
|
|
}
|
|
if (profileType == "Moderator"){
|
|
return 10000, nil
|
|
}
|
|
|
|
return 0, errors.New("GetMaximumProfilesInResponse_GetProfiles called with invalid profile type: " + profileType)
|
|
}
|
|
|
|
//Outputs:
|
|
// -[]byte: Response bytes
|
|
// -[32]byte: Connection Key
|
|
// -error
|
|
func CreateServerResponse_EstablishConnectionKey(hostPublicIdentityKey [32]byte, hostPrivateIdentityKey [64]byte, requestIdentifier [16]byte, requestorNaclPublicKey [32]byte, requestorKyberPublicKey [1568]byte)([]byte, [32]byte, error){
|
|
|
|
var connectionKey [32]byte
|
|
_, err := rand.Read(connectionKey[:])
|
|
if (err != nil) { return nil, [32]byte{}, err }
|
|
|
|
type responseStruct struct{
|
|
HostIdentityKey [32]byte
|
|
RequestIdentifier [16]byte
|
|
ResponseType string
|
|
ConnectionKey [32]byte
|
|
}
|
|
|
|
responseObject := responseStruct{
|
|
HostIdentityKey: hostPublicIdentityKey,
|
|
RequestIdentifier: requestIdentifier,
|
|
ResponseType: "EstablishConnectionKey",
|
|
ConnectionKey: connectionKey,
|
|
}
|
|
|
|
responseContentBytes, err := encoding.EncodeMessagePackBytes(responseObject)
|
|
if (err != nil) { return nil, [32]byte{}, err }
|
|
|
|
responseSignedBytes, err := createResponseSignedContent(hostPrivateIdentityKey, responseContentBytes)
|
|
if (err != nil) { return nil, [32]byte{}, err }
|
|
|
|
chaPolyKey, err := helpers.GetNewRandom32ByteArray()
|
|
if (err != nil) { return nil, [32]byte{}, err }
|
|
|
|
chaPolyNonce, err := helpers.GetNewRandom24ByteArray()
|
|
if (err != nil) { return nil, [32]byte{}, err }
|
|
|
|
cipheredContent, err := chaPolyShrink.EncryptChaPolyShrink(responseSignedBytes, chaPolyKey, chaPolyNonce, true, 50, false, [32]byte{})
|
|
if (err != nil) { return nil, [32]byte{}, err }
|
|
|
|
keyPieceA, err := helpers.GetNewRandom32ByteArray()
|
|
if (err != nil) { return nil, [32]byte{}, err }
|
|
|
|
keyPieceB := helpers.XORTwo32ByteArrays(keyPieceA, chaPolyKey)
|
|
|
|
naclEncryptedKeyPieceA, err := nacl.EncryptKeyWithNacl(requestorNaclPublicKey, keyPieceA)
|
|
if (err != nil) { return nil, [32]byte{}, err }
|
|
|
|
kyberEncryptedKeyPieceB, err := kyber.EncryptKeyWithKyber(requestorKyberPublicKey, keyPieceB)
|
|
if (err != nil) { return nil, [32]byte{}, err }
|
|
|
|
keyPiecesList := slices.Concat(naclEncryptedKeyPieceA[:], kyberEncryptedKeyPieceB[:])
|
|
|
|
type encryptedResponseStruct struct{
|
|
KeyPieces []byte
|
|
ChaPolyNonce [24]byte
|
|
CipheredContent []byte
|
|
}
|
|
|
|
encryptedResponseObject := encryptedResponseStruct{
|
|
KeyPieces: keyPiecesList,
|
|
ChaPolyNonce: chaPolyNonce,
|
|
CipheredContent: cipheredContent,
|
|
}
|
|
|
|
encryptedResponseBytes, err := encoding.EncodeMessagePackBytes(encryptedResponseObject)
|
|
if (err != nil) { return nil, [32]byte{}, err }
|
|
|
|
return encryptedResponseBytes, connectionKey, nil
|
|
}
|
|
|
|
//Outputs:
|
|
// -bool: Able to read
|
|
// -[16]byte: Request identifier
|
|
// -[16]byte: Host Identity Hash
|
|
// -[32]byte: Connection key
|
|
// -error (if inputs to function are invalid)
|
|
func ReadServerResponse_EstablishConnectionKey(responseBytes []byte, requestorNaclPublicKey [32]byte, requestorNaclPrivateKey [32]byte, requestorKyberPrivateKey [1536]byte)(bool, [16]byte, [16]byte, [32]byte, error){
|
|
|
|
type encryptedResponseStruct struct{
|
|
KeyPieces [1648]byte
|
|
ChaPolyNonce [24]byte
|
|
CipheredContent []byte
|
|
}
|
|
|
|
var encryptedResponseObject encryptedResponseStruct
|
|
|
|
err := encoding.DecodeMessagePackBytes(false, responseBytes, &encryptedResponseObject)
|
|
if (err != nil) {
|
|
return false, [16]byte{}, [16]byte{}, [32]byte{}, nil
|
|
}
|
|
|
|
keyPiecesListArray := encryptedResponseObject.KeyPieces
|
|
chaPolyNonce := encryptedResponseObject.ChaPolyNonce
|
|
cipheredContent := encryptedResponseObject.CipheredContent
|
|
|
|
naclEncryptedKeyPieceA := [80]byte(keyPiecesListArray[:80])
|
|
kyberEncryptedKeyPieceB := [1568]byte(keyPiecesListArray[80:])
|
|
|
|
ableToDecrypt, keyPieceA, err := nacl.DecryptNaclEncryptedKey(naclEncryptedKeyPieceA, requestorNaclPublicKey, requestorNaclPrivateKey)
|
|
if (err != nil) { return false, [16]byte{}, [16]byte{}, [32]byte{}, err }
|
|
if (ableToDecrypt == false){
|
|
return false, [16]byte{}, [16]byte{}, [32]byte{}, nil
|
|
}
|
|
|
|
keyPieceB, err := kyber.DecryptKyberEncryptedKey(kyberEncryptedKeyPieceB, requestorKyberPrivateKey)
|
|
if (err != nil) {
|
|
return false, [16]byte{}, [16]byte{}, [32]byte{}, nil
|
|
}
|
|
|
|
contentChaPolyKey := helpers.XORTwo32ByteArrays(keyPieceA, keyPieceB)
|
|
|
|
ableToDecrypt, decryptedResponseBytes, err := chaPolyShrink.DecryptChaPolyShrink(cipheredContent, contentChaPolyKey, chaPolyNonce, false, [32]byte{})
|
|
if (err != nil) {
|
|
return false, [16]byte{}, [16]byte{}, [32]byte{}, nil
|
|
}
|
|
if (ableToDecrypt == false){
|
|
return false, [16]byte{}, [16]byte{}, [32]byte{}, nil
|
|
}
|
|
|
|
ableToRead, requestIdentifier, hostIdentityHash, contentBytes, err := readResponseSignedContent(decryptedResponseBytes, "EstablishConnectionKey")
|
|
if (err != nil) { return false, [16]byte{}, [16]byte{}, [32]byte{}, err }
|
|
if (ableToRead == false){
|
|
return false, [16]byte{}, [16]byte{}, [32]byte{}, nil
|
|
}
|
|
|
|
type responseContentStruct struct{
|
|
ConnectionKey [32]byte
|
|
}
|
|
|
|
var responseContentObject responseContentStruct
|
|
|
|
err = encoding.DecodeMessagePackBytes(true, contentBytes, &responseContentObject)
|
|
if (err != nil) {
|
|
return false, [16]byte{}, [16]byte{}, [32]byte{}, nil
|
|
}
|
|
|
|
connectionKey := responseContentObject.ConnectionKey
|
|
|
|
return true, requestIdentifier, hostIdentityHash, connectionKey, nil
|
|
}
|
|
|
|
|
|
//Outputs:
|
|
// -[]byte: Response bytes
|
|
// -error
|
|
func CreateServerResponse_GetParametersInfo(hostPublicIdentityKey [32]byte, hostPrivateIdentityKey [64]byte, connectionKey [32]byte, requestIdentifier [16]byte, parametersInfoMap map[string]int64)([]byte, error){
|
|
|
|
if (len(parametersInfoMap) == 0){
|
|
return nil, errors.New("CreateServerResponse_GetParametersInfo called with empty ParametersInfoMap")
|
|
}
|
|
|
|
type responseContentStruct struct{
|
|
HostIdentityKey [32]byte
|
|
RequestIdentifier [16]byte
|
|
ResponseType string
|
|
ParametersInfo map[string]int64 // Parameters Type -> Parameters broadcast time
|
|
}
|
|
|
|
responseContentObject := responseContentStruct{
|
|
HostIdentityKey: hostPublicIdentityKey,
|
|
RequestIdentifier: requestIdentifier,
|
|
ResponseType: "GetParametersInfo",
|
|
ParametersInfo: parametersInfoMap,
|
|
}
|
|
|
|
innerResponseBytes, err := encoding.EncodeMessagePackBytes(responseContentObject)
|
|
if (err != nil) { return nil, err }
|
|
|
|
encryptedResponse, err := createEncryptedAndSignedResponse(connectionKey, hostPrivateIdentityKey, innerResponseBytes)
|
|
if (err != nil) { return nil, err }
|
|
|
|
return encryptedResponse, nil
|
|
}
|
|
|
|
//Outputs:
|
|
// -bool: Able to read server response
|
|
// -[16]byte: Request Identifier
|
|
// -[16]byte: Host Identity Hash
|
|
// -map[string]int64: Parameters Info map (Parameters Type -> Parameters broadcast time)
|
|
// -error (returns err if input keys are invalid)
|
|
func ReadServerResponse_GetParametersInfo(responseBytes []byte, connectionKey [32]byte)(bool, [16]byte, [16]byte, map[string]int64, error){
|
|
|
|
ableToRead, requestIdentifier, hostIdentityHash, decryptedContentBytes, err := readEncryptedAndSignedResponse(responseBytes, connectionKey, "GetParametersInfo")
|
|
if (err != nil) { return false, [16]byte{}, [16]byte{}, nil, err }
|
|
if (ableToRead == false){
|
|
//Response is malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
type responseContentStruct struct{
|
|
ParametersInfo map[string]int64
|
|
}
|
|
|
|
var responseContentObject responseContentStruct
|
|
|
|
err = encoding.DecodeMessagePackBytes(true, decryptedContentBytes, &responseContentObject)
|
|
if (err != nil) {
|
|
// Response malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
parametersInfoMap := responseContentObject.ParametersInfo
|
|
|
|
//TODO: Verify parameters
|
|
|
|
return true, requestIdentifier, hostIdentityHash, parametersInfoMap, nil
|
|
}
|
|
|
|
|
|
//Outputs:
|
|
// -[]byte: Response bytes
|
|
// -error
|
|
func CreateServerResponse_GetParameters(hostPublicIdentityKey [32]byte, hostPrivateIdentityKey [64]byte, connectionKey [32]byte, requestIdentifier [16]byte, parametersList [][]byte)([]byte, error){
|
|
|
|
//TODO: Verify inputs
|
|
|
|
messagepackParametersList := make([]messagepack.RawMessage, 0, len(parametersList))
|
|
|
|
for _, parametersBytes := range parametersList{
|
|
messagepackParametersList = append(messagepackParametersList, parametersBytes)
|
|
}
|
|
|
|
type responseContentStruct struct{
|
|
HostIdentityKey [32]byte
|
|
RequestIdentifier [16]byte
|
|
ResponseType string
|
|
ParametersList []messagepack.RawMessage
|
|
}
|
|
|
|
responseContentObject := responseContentStruct{
|
|
HostIdentityKey: hostPublicIdentityKey,
|
|
RequestIdentifier: requestIdentifier,
|
|
ResponseType: "GetParameters",
|
|
ParametersList: messagepackParametersList,
|
|
}
|
|
|
|
innerResponseBytes, err := encoding.EncodeMessagePackBytes(responseContentObject)
|
|
if (err != nil) { return nil, err }
|
|
|
|
encryptedResponse, err := createEncryptedAndSignedResponse(connectionKey, hostPrivateIdentityKey, innerResponseBytes)
|
|
if (err != nil) { return nil, err }
|
|
|
|
return encryptedResponse, nil
|
|
}
|
|
|
|
|
|
//Outputs:
|
|
// -bool: Able to read server response
|
|
// -[16]byte: Request Identifier
|
|
// -[16]byte: Host Identity Hash
|
|
// -[][]byte: Parameters list
|
|
// -error (returns err if input keys are invalid)
|
|
func ReadServerResponse_GetParameters(responseBytes []byte, connectionKey [32]byte)(bool, [16]byte, [16]byte, [][]byte, error){
|
|
|
|
//TODO: Verify inputs
|
|
|
|
ableToRead, requestIdentifier, hostIdentityHash, decryptedContentBytes, err := readEncryptedAndSignedResponse(responseBytes, connectionKey, "GetParameters")
|
|
if (err != nil) { return false, [16]byte{}, [16]byte{}, nil, err }
|
|
if (ableToRead == false){
|
|
//Response is malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
type responseContentStruct struct{
|
|
ParametersList []messagepack.RawMessage
|
|
}
|
|
|
|
var responseContentObject responseContentStruct
|
|
|
|
err = encoding.DecodeMessagePackBytes(true, decryptedContentBytes, &responseContentObject)
|
|
if (err != nil) {
|
|
// Response is malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
parametersListRawMessagepack := responseContentObject.ParametersList
|
|
|
|
// We use the map below to ensure we only received each parameter type once
|
|
receivedParametersTypesMap := make(map[string]struct{})
|
|
|
|
// We use this to ensure that all parameters network types are the same
|
|
parametersNetworkType := byte(0)
|
|
|
|
parametersList := make([][]byte, 0, len(parametersListRawMessagepack))
|
|
|
|
for index, parametersBytes := range parametersListRawMessagepack{
|
|
|
|
ableToRead, _, currentNetworkType, _, parametersType, _, _, err := readParameters.ReadParameters(true, parametersBytes)
|
|
if (err != nil) { return false, [16]byte{}, [16]byte{}, nil, err }
|
|
if (ableToRead == false){
|
|
// Response is malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
if (index == 0){
|
|
parametersNetworkType = currentNetworkType
|
|
|
|
} else if (parametersNetworkType != currentNetworkType){
|
|
|
|
// We received two parameters with different network types.
|
|
// Response is malformed.
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
_, exists := receivedParametersTypesMap[parametersType]
|
|
if (exists == true){
|
|
// We received a duplicate parameters type. Response is malformed.
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
receivedParametersTypesMap[parametersType] = struct{}{}
|
|
|
|
parametersList = append(parametersList, parametersBytes)
|
|
}
|
|
|
|
return true, requestIdentifier, hostIdentityHash, parametersList, nil
|
|
}
|
|
|
|
// This is used for the GetProfilesInfo request
|
|
type ProfileInfoStruct struct{
|
|
ProfileHash [28]byte
|
|
ProfileAuthor [16]byte
|
|
ProfileBroadcastTime int64
|
|
}
|
|
|
|
//Outputs:
|
|
// -[]byte: Response bytes
|
|
// -error
|
|
func CreateServerResponse_GetProfilesInfo(hostPublicIdentityKey [32]byte, hostPrivateIdentityKey [64]byte, connectionKey [32]byte, requestIdentifier [16]byte, profileInfoObjectsList []ProfileInfoStruct)([]byte, error){
|
|
|
|
//TODO: Verify inputs
|
|
|
|
for _, profileInfoObject := range profileInfoObjectsList{
|
|
|
|
profileHash := profileInfoObject.ProfileHash
|
|
profileAuthor := profileInfoObject.ProfileAuthor
|
|
profileBroadcastTime := profileInfoObject.ProfileBroadcastTime
|
|
|
|
profileType, _, err := readProfiles.ReadProfileHashMetadata(profileHash)
|
|
if (err != nil){
|
|
profileHashHex := encoding.EncodeBytesToHexString(profileHash[:])
|
|
return nil, errors.New("Cannot create response: Invalid profileInfoObjectsList: Invalid ProfileHash: " + profileHashHex + ". Reason: " + err.Error())
|
|
}
|
|
|
|
authorIdentityType, err := identity.GetIdentityTypeFromIdentityHash(profileAuthor)
|
|
if (err != nil){
|
|
profileAuthorHex := encoding.EncodeBytesToHexString(profileAuthor[:])
|
|
return nil, errors.New("Cannot create response: invalid profileInfoObjectsList: Invalid profileAuthor: " + profileAuthorHex)
|
|
}
|
|
|
|
if (authorIdentityType != profileType){
|
|
return nil, errors.New("Cannot create response: Invalid profileInfoObjectsList: ProfileHash profile type does not match profileAuthor identity type.")
|
|
}
|
|
|
|
isValid := helpers.VerifyBroadcastTime(profileBroadcastTime)
|
|
if (isValid == false){
|
|
broadcastTimeString := helpers.ConvertInt64ToString(profileBroadcastTime)
|
|
return nil, errors.New("Cannot create response: Invalid profileInfoObjectsList: Invalid broadcastTime: " + broadcastTimeString)
|
|
}
|
|
}
|
|
|
|
type responseContentStruct struct{
|
|
HostIdentityKey [32]byte
|
|
RequestIdentifier [16]byte
|
|
ResponseType string
|
|
ProfilesInfo []ProfileInfoStruct
|
|
}
|
|
|
|
responseContentObject := responseContentStruct{
|
|
HostIdentityKey: hostPublicIdentityKey,
|
|
RequestIdentifier: requestIdentifier,
|
|
ResponseType: "GetProfilesInfo",
|
|
ProfilesInfo: profileInfoObjectsList,
|
|
}
|
|
|
|
innerResponseBytes, err := encoding.EncodeMessagePackBytes(responseContentObject)
|
|
if (err != nil) { return nil, err }
|
|
|
|
encryptedResponse, err := createEncryptedAndSignedResponse(connectionKey, hostPrivateIdentityKey, innerResponseBytes)
|
|
if (err != nil) { return nil, err }
|
|
|
|
return encryptedResponse, nil
|
|
}
|
|
|
|
|
|
//Outputs:
|
|
// -bool: Able to read server response
|
|
// -[16]byte: Request Identifier
|
|
// -[16]byte: Host Identity Hash
|
|
// -[]ProfileInfoStruct: Profiles Info map list
|
|
// -error (returns err if input keys are invalid)
|
|
func ReadServerResponse_GetProfilesInfo(responseBytes []byte, connectionKey [32]byte)(bool, [16]byte, [16]byte, []ProfileInfoStruct, error){
|
|
|
|
//TODO: Verify inputs
|
|
|
|
ableToRead, requestIdentifier, hostIdentityHash, decryptedContentBytes, err := readEncryptedAndSignedResponse(responseBytes, connectionKey, "GetProfilesInfo")
|
|
if (err != nil) { return false, [16]byte{}, [16]byte{}, nil, err }
|
|
if (ableToRead == false){
|
|
//Response is malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
type responseContentStruct struct{
|
|
ProfilesInfo []ProfileInfoStruct
|
|
}
|
|
|
|
var responseContentObject responseContentStruct
|
|
|
|
err = encoding.DecodeMessagePackBytes(true, decryptedContentBytes, &responseContentObject)
|
|
if (err != nil) {
|
|
// Response malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
//TODO: Validate info
|
|
profileInfoObjectsList := responseContentObject.ProfilesInfo
|
|
|
|
return true, requestIdentifier, hostIdentityHash, profileInfoObjectsList, nil
|
|
}
|
|
|
|
|
|
//Outputs:
|
|
// -[]byte: Response bytes
|
|
// -error
|
|
func CreateServerResponse_GetProfiles(hostPublicIdentityKey [32]byte, hostPrivateIdentityKey [64]byte, connectionKey [32]byte, requestIdentifier [16]byte, profilesList [][]byte)([]byte, error){
|
|
|
|
//TODO: Verify inputs
|
|
|
|
messagepackProfilesList := make([]messagepack.RawMessage, 0, len(profilesList))
|
|
|
|
for _, profileBytes := range profilesList{
|
|
|
|
messagepackProfilesList = append(messagepackProfilesList, profileBytes)
|
|
}
|
|
|
|
type responseContentStruct struct{
|
|
HostIdentityKey [32]byte
|
|
RequestIdentifier [16]byte
|
|
ResponseType string
|
|
ProfilesList []messagepack.RawMessage
|
|
}
|
|
|
|
responseContentObject := responseContentStruct{
|
|
HostIdentityKey: hostPublicIdentityKey,
|
|
RequestIdentifier: requestIdentifier,
|
|
ResponseType: "GetProfiles",
|
|
ProfilesList: messagepackProfilesList,
|
|
}
|
|
|
|
innerResponseBytes, err := encoding.EncodeMessagePackBytes(responseContentObject)
|
|
if (err != nil) { return nil, err }
|
|
|
|
encryptedResponse, err := createEncryptedAndSignedResponse(connectionKey, hostPrivateIdentityKey, innerResponseBytes)
|
|
if (err != nil) { return nil, err }
|
|
|
|
return encryptedResponse, nil
|
|
}
|
|
|
|
|
|
//Outputs:
|
|
// -bool: Able to read server response
|
|
// -[16]byte: Request Identifier
|
|
// -[16]byte: Host Identity Hash
|
|
// -[][]byte: Profiles list
|
|
// -error (returns err if input keys are invalid)
|
|
func ReadServerResponse_GetProfiles(responseBytes []byte, connectionKey [32]byte)(bool, [16]byte, [16]byte, [][]byte, error){
|
|
|
|
//TODO: Verify inputs
|
|
|
|
ableToRead, requestIdentifier, hostIdentityHash, decryptedContentBytes, err := readEncryptedAndSignedResponse(responseBytes, connectionKey, "GetProfiles")
|
|
if (err != nil) { return false, [16]byte{}, [16]byte{}, nil, err }
|
|
if (ableToRead == false){
|
|
//Response is malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
type responseContentStruct struct{
|
|
ProfilesList []messagepack.RawMessage
|
|
}
|
|
|
|
var responseContentObject responseContentStruct
|
|
|
|
err = encoding.DecodeMessagePackBytes(true, decryptedContentBytes, &responseContentObject)
|
|
if (err != nil) {
|
|
// Response is malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
messagepackProfilesList := responseContentObject.ProfilesList
|
|
|
|
// We use the map below to ensure we only received each profile once
|
|
receivedProfileHashesMap := make(map[[28]byte]struct{})
|
|
|
|
profilesList := make([][]byte, 0, len(messagepackProfilesList))
|
|
|
|
// We use this variable to make sure the network type of each profile is the same
|
|
profilesNetworkType := byte(0)
|
|
|
|
for index, profileBytes := range messagepackProfilesList{
|
|
|
|
ableToRead, profileHash, _, profileNetworkType, _, _, _, _, err := readProfiles.ReadProfileAndHash(true, profileBytes)
|
|
if (err != nil) { return false, [16]byte{}, [16]byte{}, nil, err }
|
|
if (ableToRead == false){
|
|
// Profile is malformed. Host is malicious.
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
_, exists := receivedProfileHashesMap[profileHash]
|
|
if (exists == true){
|
|
// We received a duplicate profile. Host is malicious.
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
receivedProfileHashesMap[profileHash] = struct{}{}
|
|
|
|
if (index == 0){
|
|
profilesNetworkType = profileNetworkType
|
|
|
|
} else if (profilesNetworkType != profileNetworkType){
|
|
// Profiles of differing network type cannot be sent in the same response
|
|
// Response is malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
profilesList = append(profilesList, profileBytes)
|
|
}
|
|
|
|
return true, requestIdentifier, hostIdentityHash, profilesList, nil
|
|
}
|
|
|
|
|
|
//Outputs:
|
|
// -[]byte: Response bytes
|
|
// -error
|
|
func CreateServerResponse_GetMessageHashesList(hostPublicIdentityKey [32]byte, hostPrivateIdentityKey [64]byte, connectionKey [32]byte, requestIdentifier [16]byte, messageHashesList [][26]byte)([]byte, error){
|
|
|
|
type responseContentStruct struct{
|
|
HostIdentityKey [32]byte
|
|
RequestIdentifier [16]byte
|
|
ResponseType string
|
|
MessageHashesList [][26]byte
|
|
}
|
|
|
|
responseContentObject := responseContentStruct{
|
|
HostIdentityKey: hostPublicIdentityKey,
|
|
RequestIdentifier: requestIdentifier,
|
|
ResponseType: "GetMessageHashesList",
|
|
MessageHashesList: messageHashesList,
|
|
}
|
|
|
|
innerResponseBytes, err := encoding.EncodeMessagePackBytes(responseContentObject)
|
|
if (err != nil) { return nil, err }
|
|
|
|
encryptedResponse, err := createEncryptedAndSignedResponse(connectionKey, hostPrivateIdentityKey, innerResponseBytes)
|
|
if (err != nil) { return nil, err }
|
|
|
|
return encryptedResponse, nil
|
|
}
|
|
|
|
|
|
//Outputs:
|
|
// -bool: Able to read server response
|
|
// -[16]byte: Request Identifier
|
|
// -[16]byte: Host Identity Hash
|
|
// -[][26]byte: Message Hashes List
|
|
// -error (returns err if input keys are invalid)
|
|
func ReadServerResponse_GetMessageHashesList(responseBytes []byte, connectionKey [32]byte)(bool, [16]byte, [16]byte, [][26]byte, error){
|
|
|
|
//TODO: Verify inputs
|
|
|
|
ableToRead, requestIdentifier, hostIdentityHash, decryptedContentBytes, err := readEncryptedAndSignedResponse(responseBytes, connectionKey, "GetMessageHashesList")
|
|
if (err != nil) { return false, [16]byte{}, [16]byte{}, nil, err }
|
|
if (ableToRead == false){
|
|
//Response is malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
type responseContentStruct struct{
|
|
MessageHashesList [][26]byte
|
|
}
|
|
|
|
var responseContentObject responseContentStruct
|
|
|
|
err = encoding.DecodeMessagePackBytes(true, decryptedContentBytes, &responseContentObject)
|
|
if (err != nil) {
|
|
// Response malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
messageHashesList := responseContentObject.MessageHashesList
|
|
|
|
return true, requestIdentifier, hostIdentityHash, messageHashesList, nil
|
|
}
|
|
|
|
|
|
//Outputs:
|
|
// -[]byte: Response bytes
|
|
// -error
|
|
func CreateServerResponse_GetMessages(hostPublicIdentityKey [32]byte, hostPrivateIdentityKey [64]byte, connectionKey [32]byte, requestIdentifier [16]byte, messagesList [][]byte)([]byte, error){
|
|
|
|
//TODO: Verify inputs
|
|
|
|
messagepackMessagesList := make([]messagepack.RawMessage, 0, len(messagesList))
|
|
|
|
for _, messageBytes := range messagesList{
|
|
messagepackMessagesList = append(messagepackMessagesList, messageBytes)
|
|
}
|
|
|
|
type responseContentStruct struct{
|
|
HostIdentityKey [32]byte
|
|
RequestIdentifier [16]byte
|
|
ResponseType string
|
|
MessagesList []messagepack.RawMessage
|
|
}
|
|
|
|
responseContentObject := responseContentStruct{
|
|
HostIdentityKey: hostPublicIdentityKey,
|
|
RequestIdentifier: requestIdentifier,
|
|
ResponseType: "GetMessages",
|
|
MessagesList: messagepackMessagesList,
|
|
}
|
|
|
|
innerResponseBytes, err := encoding.EncodeMessagePackBytes(responseContentObject)
|
|
if (err != nil) { return nil, err }
|
|
|
|
encryptedResponse, err := createEncryptedAndSignedResponse(connectionKey, hostPrivateIdentityKey, innerResponseBytes)
|
|
if (err != nil) { return nil, err }
|
|
|
|
return encryptedResponse, nil
|
|
}
|
|
|
|
|
|
//Outputs:
|
|
// -bool: Able to read server response
|
|
// -[16]byte: Request Identifier
|
|
// -[16]byte: Host Identity Hash
|
|
// -[][]byte: Messages list
|
|
// -error (returns err if input keys are invalid)
|
|
func ReadServerResponse_GetMessages(responseBytes []byte, connectionKey [32]byte)(bool, [16]byte, [16]byte, [][]byte, error){
|
|
|
|
//TODO: Verify inputs
|
|
|
|
ableToRead, requestIdentifier, hostIdentityHash, decryptedContentBytes, err := readEncryptedAndSignedResponse(responseBytes, connectionKey, "GetMessages")
|
|
if (err != nil) { return false, [16]byte{}, [16]byte{}, nil, err }
|
|
if (ableToRead == false){
|
|
//Response is malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
type responseContentStruct struct{
|
|
MessagesList []messagepack.RawMessage
|
|
}
|
|
|
|
var responseContentObject responseContentStruct
|
|
|
|
err = encoding.DecodeMessagePackBytes(true, decryptedContentBytes, &responseContentObject)
|
|
if (err != nil) {
|
|
// Response is malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
messagepackMessagesList := responseContentObject.MessagesList
|
|
|
|
// We use this map to detect duplicates
|
|
messageHashesMap := make(map[[26]byte]struct{})
|
|
|
|
messagesList := make([][]byte, 0, len(messagepackMessagesList))
|
|
|
|
// We use this variable to make sure the network type of all messages in the response is the same
|
|
messagesNetworkType := byte(0)
|
|
|
|
for index, messageBytes := range messagepackMessagesList{
|
|
|
|
ableToRead, messageHash, _, messageNetworkType, _, _, _, _, _, _, _, err := readMessages.ReadChatMessagePublicDataAndHash(true, messageBytes)
|
|
if (err != nil) { return false, [16]byte{}, [16]byte{}, nil, err }
|
|
if (ableToRead == false){
|
|
// Message is invalid, host must be malicious.
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
_, exists := messageHashesMap[messageHash]
|
|
if (exists == true){
|
|
// Host sent duplicate message.
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
messageHashesMap[messageHash] = struct{}{}
|
|
|
|
if (index == 0){
|
|
messagesNetworkType = messageNetworkType
|
|
|
|
} else if (messagesNetworkType != messageNetworkType){
|
|
// All messages in the response must contain the same networkType
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
messagesList = append(messagesList, messageBytes)
|
|
}
|
|
|
|
return true, requestIdentifier, hostIdentityHash, messagesList, nil
|
|
}
|
|
|
|
|
|
//Outputs:
|
|
// -[]byte: Response bytes
|
|
// -error
|
|
func CreateServerResponse_GetIdentityReviewsInfo(hostPublicIdentityKey [32]byte, hostPrivateIdentityKey [64]byte, connectionKey [32]byte, requestIdentifier [16]byte, reviewsInfoMap map[[29]byte][]byte)([]byte, error){
|
|
|
|
//TODO: Verify inputs
|
|
|
|
type responseContentStruct struct{
|
|
HostIdentityKey [32]byte
|
|
RequestIdentifier [16]byte
|
|
ResponseType string
|
|
ReviewsInfo map[[29]byte][]byte // ReviewHash -> ReviewedHash
|
|
}
|
|
|
|
responseContentObject := responseContentStruct{
|
|
HostIdentityKey: hostPublicIdentityKey,
|
|
RequestIdentifier: requestIdentifier,
|
|
ResponseType: "GetIdentityReviewsInfo",
|
|
ReviewsInfo: reviewsInfoMap,
|
|
}
|
|
|
|
innerResponseBytes, err := encoding.EncodeMessagePackBytes(responseContentObject)
|
|
if (err != nil) { return nil, err }
|
|
|
|
encryptedResponse, err := createEncryptedAndSignedResponse(connectionKey, hostPrivateIdentityKey, innerResponseBytes)
|
|
if (err != nil) { return nil, err }
|
|
|
|
return encryptedResponse, nil
|
|
}
|
|
|
|
|
|
//Outputs:
|
|
// -bool: Able to read server response
|
|
// -[16]byte: Request Identifier
|
|
// -[16]byte: Host Identity Hash
|
|
// -map[[29]byte][]byte: Reviews Info map (Review Hash -> Reviewed Hash)
|
|
// -error (returns err if input keys are invalid)
|
|
func ReadServerResponse_GetIdentityReviewsInfo(responseBytes []byte, connectionKey [32]byte)(bool, [16]byte, [16]byte, map[[29]byte][]byte, error){
|
|
|
|
//TODO: Verify inputs
|
|
|
|
ableToRead, requestIdentifier, hostIdentityHash, decryptedContentBytes, err := readEncryptedAndSignedResponse(responseBytes, connectionKey, "GetIdentityReviewsInfo")
|
|
if (err != nil) { return false, [16]byte{}, [16]byte{}, nil, err }
|
|
if (ableToRead == false){
|
|
//Response is malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
type responseContentStruct struct{
|
|
ReviewsInfo map[[29]byte][]byte
|
|
}
|
|
|
|
var responseContentObject responseContentStruct
|
|
|
|
err = encoding.DecodeMessagePackBytes(true, decryptedContentBytes, &responseContentObject)
|
|
if (err != nil) {
|
|
// Response malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
reviewsInfoMap := responseContentObject.ReviewsInfo
|
|
|
|
for reviewHash, reviewedHash := range reviewsInfoMap{
|
|
|
|
reviewedType, err := helpers.GetReviewedTypeFromReviewedHash(reviewedHash)
|
|
if (err != nil) {
|
|
// Response is malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
if (reviewedType != "Identity" && reviewedType != "Profile" && reviewedType != "Attribute"){
|
|
// Response is malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
isValid, err := readReviews.VerifyReviewHash(reviewHash, true, reviewedType)
|
|
if (err != nil) { return false, [16]byte{}, [16]byte{}, nil, err }
|
|
if (isValid == false){
|
|
// Received reviewsInfoMap contains invalid reviewHash
|
|
// Response is malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
}
|
|
|
|
return true, requestIdentifier, hostIdentityHash, reviewsInfoMap, nil
|
|
}
|
|
|
|
|
|
//Outputs:
|
|
// -[]byte: Response bytes
|
|
// -error
|
|
func CreateServerResponse_GetMessageReviewsInfo(hostPublicIdentityKey [32]byte, hostPrivateIdentityKey [64]byte, connectionKey [32]byte, requestIdentifier [16]byte, reviewsInfoMap map[[29]byte][26]byte)([]byte, error){
|
|
|
|
//TODO: Verify inputs
|
|
|
|
type responseContentStruct struct{
|
|
HostIdentityKey [32]byte
|
|
RequestIdentifier [16]byte
|
|
ResponseType string
|
|
ReviewsInfo map[[29]byte][26]byte // Review Hash -> Reviewed Message Hash
|
|
}
|
|
|
|
responseContentObject := responseContentStruct{
|
|
HostIdentityKey: hostPublicIdentityKey,
|
|
RequestIdentifier: requestIdentifier,
|
|
ResponseType: "GetMessageReviewsInfo",
|
|
ReviewsInfo: reviewsInfoMap,
|
|
}
|
|
|
|
innerResponseBytes, err := encoding.EncodeMessagePackBytes(responseContentObject)
|
|
if (err != nil) { return nil, err }
|
|
|
|
encryptedResponse, err := createEncryptedAndSignedResponse(connectionKey, hostPrivateIdentityKey, innerResponseBytes)
|
|
if (err != nil) { return nil, err }
|
|
|
|
return encryptedResponse, nil
|
|
}
|
|
|
|
|
|
//Outputs:
|
|
// -bool: Able to read server response
|
|
// -[16]byte: Request Identifier
|
|
// -[16]byte: Host Identity Hash
|
|
// -map[[29]byte][26]byte: Reviews Info map (Review Hash -> Reviewed Message Hash)
|
|
// -error (returns err if input keys are invalid)
|
|
func ReadServerResponse_GetMessageReviewsInfo(responseBytes []byte, connectionKey [32]byte)(bool, [16]byte, [16]byte, map[[29]byte][26]byte, error){
|
|
|
|
//TODO: Verify inputs
|
|
|
|
ableToRead, requestIdentifier, hostIdentityHash, decryptedContentBytes, err := readEncryptedAndSignedResponse(responseBytes, connectionKey, "GetMessageReviewsInfo")
|
|
if (err != nil) { return false, [16]byte{}, [16]byte{}, nil, err }
|
|
if (ableToRead == false){
|
|
//Response is malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
type responseContentStruct struct{
|
|
ReviewsInfo map[[29]byte][26]byte
|
|
}
|
|
|
|
var responseContentObject responseContentStruct
|
|
|
|
err = encoding.DecodeMessagePackBytes(true, decryptedContentBytes, &responseContentObject)
|
|
if (err != nil) {
|
|
// Response malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
reviewsInfoMap := responseContentObject.ReviewsInfo
|
|
|
|
for reviewHash, _ := range reviewsInfoMap{
|
|
|
|
isValid, err := readReviews.VerifyReviewHash(reviewHash, true, "Message")
|
|
if (err != nil) { return false, [16]byte{}, [16]byte{}, nil, err }
|
|
if (isValid == false){
|
|
// Received reviewsInfoMap contains invalid reviewHash
|
|
// Response is malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
}
|
|
|
|
return true, requestIdentifier, hostIdentityHash, reviewsInfoMap, nil
|
|
}
|
|
|
|
|
|
//Outputs:
|
|
// -[]byte: Response bytes
|
|
// -error
|
|
func CreateServerResponse_GetReviews(hostPublicIdentityKey [32]byte, hostPrivateIdentityKey [64]byte, connectionKey [32]byte, requestIdentifier [16]byte, reviewsList [][]byte)([]byte, error){
|
|
|
|
//TODO: Verify inputs
|
|
|
|
messagepackReviewsList := make([]messagepack.RawMessage, 0, len(reviewsList))
|
|
|
|
for _, reviewBytes := range reviewsList{
|
|
messagepackReviewsList = append(messagepackReviewsList, reviewBytes)
|
|
}
|
|
|
|
type responseContentStruct struct{
|
|
HostIdentityKey [32]byte
|
|
RequestIdentifier [16]byte
|
|
ResponseType string
|
|
ReviewsList []messagepack.RawMessage
|
|
}
|
|
|
|
responseContentObject := responseContentStruct{
|
|
HostIdentityKey: hostPublicIdentityKey,
|
|
RequestIdentifier: requestIdentifier,
|
|
ResponseType: "GetReviews",
|
|
ReviewsList: messagepackReviewsList,
|
|
}
|
|
|
|
innerResponseBytes, err := encoding.EncodeMessagePackBytes(responseContentObject)
|
|
if (err != nil) { return nil, err }
|
|
|
|
encryptedResponse, err := createEncryptedAndSignedResponse(connectionKey, hostPrivateIdentityKey, innerResponseBytes)
|
|
if (err != nil) { return nil, err }
|
|
|
|
return encryptedResponse, nil
|
|
}
|
|
|
|
|
|
//Outputs:
|
|
// -bool: Able to read server response
|
|
// -[16]byte: Request Identifier
|
|
// -[16]byte: Host Identity Hash
|
|
// -[][]byte: Reviews list
|
|
// -error (returns err if input keys are invalid)
|
|
func ReadServerResponse_GetReviews(responseBytes []byte, connectionKey [32]byte)(bool, [16]byte, [16]byte, [][]byte, error){
|
|
|
|
//TODO: Verify inputs
|
|
|
|
ableToRead, requestIdentifier, hostIdentityHash, decryptedContentBytes, err := readEncryptedAndSignedResponse(responseBytes, connectionKey, "GetReviews")
|
|
if (err != nil) { return false, [16]byte{}, [16]byte{}, nil, err }
|
|
if (ableToRead == false){
|
|
//Response is malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
type responseContentStruct struct{
|
|
ReviewsList []messagepack.RawMessage
|
|
}
|
|
|
|
var responseContentObject responseContentStruct
|
|
|
|
err = encoding.DecodeMessagePackBytes(true, decryptedContentBytes, &responseContentObject)
|
|
if (err != nil) {
|
|
// Response is malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
messagepackReviewsList := responseContentObject.ReviewsList
|
|
|
|
// We use a map to detect duplicates
|
|
reviewHashesMap := make(map[[29]byte]struct{})
|
|
|
|
reviewsList := make([][]byte, 0, len(messagepackReviewsList))
|
|
|
|
// We use this variable to ensure that all reviews in the response belong to the same networkType
|
|
reviewsNetworkType := byte(0)
|
|
|
|
for index, reviewBytes := range messagepackReviewsList{
|
|
|
|
ableToRead, reviewHash, _, reviewNetworkType, _, _, _, _, _, _, err := readReviews.ReadReviewAndHash(true, reviewBytes)
|
|
if (err != nil) { return false, [16]byte{}, [16]byte{}, nil, err }
|
|
if (ableToRead == false){
|
|
// Review is invalid, host must be malicious.
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
_, exists := reviewHashesMap[reviewHash]
|
|
if (exists == true){
|
|
// Duplicate review exists
|
|
// Response is malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
reviewHashesMap[reviewHash] = struct{}{}
|
|
|
|
if (index == 0){
|
|
reviewsNetworkType = reviewNetworkType
|
|
|
|
} else if (reviewsNetworkType != reviewNetworkType){
|
|
|
|
// Response contains two reviews with differing networkType
|
|
// Response is malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
reviewsList = append(reviewsList, reviewBytes)
|
|
}
|
|
|
|
return true, requestIdentifier, hostIdentityHash, reviewsList, nil
|
|
}
|
|
|
|
|
|
//Outputs:
|
|
// -[]byte: Response bytes
|
|
// -error
|
|
func CreateServerResponse_GetIdentityReportsInfo(hostPublicIdentityKey [32]byte, hostPrivateIdentityKey [64]byte, connectionKey [32]byte, requestIdentifier [16]byte, reportsInfoMap map[[30]byte][]byte)([]byte, error){
|
|
|
|
//TODO: Verify inputs
|
|
|
|
type responseContentStruct struct{
|
|
HostIdentityKey [32]byte
|
|
RequestIdentifier [16]byte
|
|
ResponseType string
|
|
ReportsInfo map[[30]byte][]byte // Report hash -> Reported hash
|
|
}
|
|
|
|
responseContentObject := responseContentStruct{
|
|
HostIdentityKey: hostPublicIdentityKey,
|
|
RequestIdentifier: requestIdentifier,
|
|
ResponseType: "GetIdentityReportsInfo",
|
|
ReportsInfo: reportsInfoMap,
|
|
}
|
|
|
|
innerResponseBytes, err := encoding.EncodeMessagePackBytes(responseContentObject)
|
|
if (err != nil) { return nil, err }
|
|
|
|
encryptedResponse, err := createEncryptedAndSignedResponse(connectionKey, hostPrivateIdentityKey, innerResponseBytes)
|
|
if (err != nil) { return nil, err }
|
|
|
|
return encryptedResponse, nil
|
|
}
|
|
|
|
|
|
//Outputs:
|
|
// -bool: Able to read server response
|
|
// -[16]byte: Request Identifier
|
|
// -[16]byte: Host Identity Hash
|
|
// -map[[30]byte][]byte: Reports Info map (Report Hash -> Reported hash)
|
|
// -error (returns err if input keys are invalid)
|
|
func ReadServerResponse_GetIdentityReportsInfo(responseBytes []byte, connectionKey [32]byte)(bool, [16]byte, [16]byte, map[[30]byte][]byte, error){
|
|
|
|
//TODO: Verify inputs
|
|
|
|
ableToRead, requestIdentifier, hostIdentityHash, decryptedContentBytes, err := readEncryptedAndSignedResponse(responseBytes, connectionKey, "GetIdentityReportsInfo")
|
|
if (err != nil) { return false, [16]byte{}, [16]byte{}, nil, err }
|
|
if (ableToRead == false){
|
|
//Response is malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
type responseContentStruct struct{
|
|
ReportsInfo map[[30]byte][]byte
|
|
}
|
|
|
|
var responseContentObject responseContentStruct
|
|
|
|
err = encoding.DecodeMessagePackBytes(true, decryptedContentBytes, &responseContentObject)
|
|
if (err != nil) {
|
|
// Response malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
reportsInfoMap := responseContentObject.ReportsInfo
|
|
|
|
for reportHash, reportedHash := range reportsInfoMap{
|
|
|
|
reportedType, err := helpers.GetReportedTypeFromReportedHash(reportedHash)
|
|
if (err != nil) {
|
|
// Response is malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
if (reportedType != "Identity" && reportedType != "Profile" && reportedType != "Attribute"){
|
|
// Response is malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
isValid, err := readReports.VerifyReportHash(reportHash, true, reportedType)
|
|
if (err != nil){ return false, [16]byte{}, [16]byte{}, nil, err }
|
|
if (isValid == false){
|
|
//Response contains invalid reportHash
|
|
// Response is malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
}
|
|
|
|
return true, requestIdentifier, hostIdentityHash, reportsInfoMap, nil
|
|
}
|
|
|
|
|
|
|
|
//Outputs:
|
|
// -[]byte: Response bytes
|
|
// -error
|
|
func CreateServerResponse_GetMessageReportsInfo(hostPublicIdentityKey [32]byte, hostPrivateIdentityKey [64]byte, connectionKey [32]byte, requestIdentifier [16]byte, reportsInfoMap map[[30]byte][26]byte)([]byte, error){
|
|
|
|
//TODO: Verify inputs
|
|
|
|
type responseContentStruct struct{
|
|
HostIdentityKey [32]byte
|
|
RequestIdentifier [16]byte
|
|
ResponseType string
|
|
ReportsInfo map[[30]byte][26]byte // Report Hash -> Reported message hash
|
|
}
|
|
|
|
responseContentObject := responseContentStruct{
|
|
HostIdentityKey: hostPublicIdentityKey,
|
|
RequestIdentifier: requestIdentifier,
|
|
ResponseType: "GetMessageReportsInfo",
|
|
ReportsInfo: reportsInfoMap,
|
|
}
|
|
|
|
innerResponseBytes, err := encoding.EncodeMessagePackBytes(responseContentObject)
|
|
if (err != nil) { return nil, err }
|
|
|
|
encryptedResponse, err := createEncryptedAndSignedResponse(connectionKey, hostPrivateIdentityKey, innerResponseBytes)
|
|
if (err != nil) { return nil, err }
|
|
|
|
return encryptedResponse, nil
|
|
}
|
|
|
|
|
|
//Outputs:
|
|
// -bool: Able to read server response
|
|
// -[16]byte: Request Identifier
|
|
// -[16]byte: Host Identity Hash
|
|
// -map[[30]byte][26]byte: Reports Info map (Report hash -> Reported message hash)
|
|
// -error (returns err if input keys are invalid)
|
|
func ReadServerResponse_GetMessageReportsInfo(responseBytes []byte, connectionKey [32]byte)(bool, [16]byte, [16]byte, map[[30]byte][26]byte, error){
|
|
|
|
//TODO: Verify inputs
|
|
|
|
ableToRead, requestIdentifier, hostIdentityHash, decryptedContentBytes, err := readEncryptedAndSignedResponse(responseBytes, connectionKey, "GetMessageReportsInfo")
|
|
if (err != nil) { return false, [16]byte{}, [16]byte{}, nil, err }
|
|
if (ableToRead == false){
|
|
//Response is malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
type responseContentStruct struct{
|
|
ReportsInfo map[[30]byte][26]byte
|
|
}
|
|
|
|
var responseContentObject responseContentStruct
|
|
|
|
err = encoding.DecodeMessagePackBytes(true, decryptedContentBytes, &responseContentObject)
|
|
if (err != nil) {
|
|
// Response malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
reportsInfoMap := responseContentObject.ReportsInfo
|
|
|
|
for reportHash, _ := range reportsInfoMap{
|
|
|
|
isValid, err := readReports.VerifyReportHash(reportHash, true, "Message")
|
|
if (err != nil) { return false, [16]byte{}, [16]byte{}, nil, err }
|
|
if (isValid == false){
|
|
// Response contains invalid reportHash
|
|
// Response is malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
}
|
|
|
|
return true, requestIdentifier, hostIdentityHash, reportsInfoMap, nil
|
|
}
|
|
|
|
|
|
//Outputs:
|
|
// -[]byte: Response bytes
|
|
// -error
|
|
func CreateServerResponse_GetReports(hostPublicIdentityKey [32]byte, hostPrivateIdentityKey [64]byte, connectionKey [32]byte, requestIdentifier [16]byte, reportsList [][]byte)([]byte, error){
|
|
|
|
//TODO: Verify inputs
|
|
|
|
messagepackReportsList := make([]messagepack.RawMessage, 0, len(reportsList))
|
|
|
|
for _, reportBytes := range reportsList{
|
|
|
|
messagepackReportsList = append(messagepackReportsList, reportBytes)
|
|
}
|
|
|
|
type responseContentStruct struct{
|
|
HostIdentityKey [32]byte
|
|
RequestIdentifier [16]byte
|
|
ResponseType string
|
|
ReportsList []messagepack.RawMessage
|
|
}
|
|
|
|
responseContentObject := responseContentStruct{
|
|
HostIdentityKey: hostPublicIdentityKey,
|
|
RequestIdentifier: requestIdentifier,
|
|
ResponseType: "GetReports",
|
|
ReportsList: messagepackReportsList,
|
|
}
|
|
|
|
innerResponseBytes, err := encoding.EncodeMessagePackBytes(responseContentObject)
|
|
if (err != nil) { return nil, err }
|
|
|
|
encryptedResponse, err := createEncryptedAndSignedResponse(connectionKey, hostPrivateIdentityKey, innerResponseBytes)
|
|
if (err != nil) { return nil, err }
|
|
|
|
return encryptedResponse, nil
|
|
}
|
|
|
|
|
|
//Outputs:
|
|
// -bool: Able to read server response
|
|
// -[16]byte: Request Identifier
|
|
// -[16]byte: Host Identity Hash
|
|
// -[][]byte: Reports list
|
|
// -error (returns err if input keys are invalid)
|
|
func ReadServerResponse_GetReports(responseBytes []byte, connectionKey [32]byte)(bool, [16]byte, [16]byte, [][]byte, error){
|
|
|
|
//TODO: Verify inputs
|
|
|
|
ableToRead, requestIdentifier, hostIdentityHash, decryptedContentBytes, err := readEncryptedAndSignedResponse(responseBytes, connectionKey, "GetReports")
|
|
if (err != nil) { return false, [16]byte{}, [16]byte{}, nil, err }
|
|
if (ableToRead == false){
|
|
//Response is malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
type responseContentStruct struct{
|
|
ReportsList []messagepack.RawMessage
|
|
}
|
|
|
|
var responseContentObject responseContentStruct
|
|
|
|
err = encoding.DecodeMessagePackBytes(true, decryptedContentBytes, &responseContentObject)
|
|
if (err != nil) {
|
|
// Response is malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
messagepackReportsList := responseContentObject.ReportsList
|
|
|
|
// We use this map to detect duplicates
|
|
reportHashesMap := make(map[[30]byte]struct{})
|
|
|
|
reportsList := make([][]byte, 0, len(messagepackReportsList))
|
|
|
|
// We use this variable to ensure all reports in response belong to the same network type
|
|
reportsNetworkType := byte(0)
|
|
|
|
for index, reportBytes := range messagepackReportsList{
|
|
|
|
ableToRead, reportHash, _, reportNetworkType, _, _, _, _, err := readReports.ReadReportAndHash(true, reportBytes)
|
|
if (err != nil) { return false, [16]byte{}, [16]byte{}, nil, err }
|
|
if (ableToRead == false){
|
|
// Response is malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
_, exists := reportHashesMap[reportHash]
|
|
if (exists == true){
|
|
// A duplicate report exists
|
|
// Response is malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
reportHashesMap[reportHash] = struct{}{}
|
|
|
|
if (index == 0){
|
|
reportsNetworkType = reportNetworkType
|
|
|
|
} else if (reportsNetworkType != reportNetworkType){
|
|
// All reports in response must belong to the same network type
|
|
// Response is malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
reportsList = append(reportsList, reportBytes)
|
|
}
|
|
|
|
return true, requestIdentifier, hostIdentityHash, reportsList, nil
|
|
}
|
|
|
|
// This object type is used to represent a deposit to an address
|
|
type DepositStruct struct{
|
|
|
|
// The cryptocurrency address where funds were deposited
|
|
Address string
|
|
|
|
// The unix time of the block when deposit(s) were made
|
|
DepositTime int64
|
|
|
|
// The sum of all deposit amounts in the block to the specified address, in crypto atomic units (example: wei)
|
|
//TODO: Change this to big.Int
|
|
DepositAmount int64
|
|
}
|
|
|
|
//Outputs:
|
|
// -[]byte: Response bytes
|
|
// -error
|
|
func CreateServerResponse_GetAddressDeposits(hostPublicIdentityKey [32]byte, hostPrivateIdentityKey [64]byte, connectionKey [32]byte, requestIdentifier [16]byte, depositObjectsList []DepositStruct)([]byte, error){
|
|
|
|
//TODO: Verify inputs
|
|
|
|
type responseContentStruct struct{
|
|
HostIdentityKey [32]byte
|
|
RequestIdentifier [16]byte
|
|
ResponseType string
|
|
AddressDepositsList []DepositStruct
|
|
}
|
|
|
|
responseContentObject := responseContentStruct{
|
|
HostIdentityKey: hostPublicIdentityKey,
|
|
RequestIdentifier: requestIdentifier,
|
|
ResponseType: "GetAddressDeposits",
|
|
AddressDepositsList: depositObjectsList,
|
|
}
|
|
|
|
innerResponseBytes, err := encoding.EncodeMessagePackBytes(responseContentObject)
|
|
if (err != nil) { return nil, err }
|
|
|
|
encryptedResponse, err := createEncryptedAndSignedResponse(connectionKey, hostPrivateIdentityKey, innerResponseBytes)
|
|
if (err != nil) { return nil, err }
|
|
|
|
return encryptedResponse, nil
|
|
}
|
|
|
|
|
|
//Outputs:
|
|
// -bool: Able to read server response
|
|
// -[16]byte: Request Identifier
|
|
// -[16]byte: Host Identity Hash
|
|
// -[]DepositStruct: Deposit objects list
|
|
// -error (returns err if input keys are invalid)
|
|
func ReadServerResponse_GetAddressDeposits(responseBytes []byte, connectionKey [32]byte)(bool, [16]byte, [16]byte, []DepositStruct, error){
|
|
|
|
//TODO: Verify inputs
|
|
|
|
ableToRead, requestIdentifier, hostIdentityHash, decryptedContentBytes, err := readEncryptedAndSignedResponse(responseBytes, connectionKey, "GetAddressDeposits")
|
|
if (err != nil) { return false, [16]byte{}, [16]byte{}, nil, err }
|
|
if (ableToRead == false){
|
|
//Response is malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
type responseContentStruct struct{
|
|
AddressDepositsList []DepositStruct
|
|
}
|
|
|
|
var responseContentObject responseContentStruct
|
|
|
|
err = encoding.DecodeMessagePackBytes(true, decryptedContentBytes, &responseContentObject)
|
|
if (err != nil) {
|
|
// Response malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
addressDepositsList := responseContentObject.AddressDepositsList
|
|
|
|
//TODO: validate info
|
|
|
|
return true, requestIdentifier, hostIdentityHash, addressDepositsList, nil
|
|
}
|
|
|
|
|
|
//Outputs:
|
|
// -[]byte: Response bytes
|
|
// -error
|
|
func CreateServerResponse_GetViewableStatuses(hostPublicIdentityKey [32]byte, hostPrivateIdentityKey [64]byte, connectionKey [32]byte, requestIdentifier [16]byte, identityHashStatusesMap map[[16]byte]bool, profileHashStatusesMap map[[28]byte]bool)([]byte, error){
|
|
|
|
//TODO: Verify inputs
|
|
|
|
type responseContentStruct struct{
|
|
HostIdentityKey [32]byte
|
|
RequestIdentifier [16]byte
|
|
ResponseType string
|
|
IdentityHashStatuses map[[16]byte]bool
|
|
ProfileHashStatuses map[[28]byte]bool
|
|
}
|
|
|
|
responseContentObject := responseContentStruct{
|
|
HostIdentityKey: hostPublicIdentityKey,
|
|
RequestIdentifier: requestIdentifier,
|
|
ResponseType: "GetViewableStatuses",
|
|
IdentityHashStatuses: identityHashStatusesMap,
|
|
ProfileHashStatuses: profileHashStatusesMap,
|
|
}
|
|
|
|
innerResponseBytes, err := encoding.EncodeMessagePackBytes(responseContentObject)
|
|
if (err != nil) { return nil, err }
|
|
|
|
encryptedResponse, err := createEncryptedAndSignedResponse(connectionKey, hostPrivateIdentityKey, innerResponseBytes)
|
|
if (err != nil) { return nil, err }
|
|
|
|
return encryptedResponse, nil
|
|
}
|
|
|
|
|
|
//Outputs:
|
|
// -bool: Able to read server response
|
|
// -[16]byte: Request Identifier
|
|
// -[16]byte: Host Identity Hash
|
|
// -map[[16]byte]bool: Identity Hash Statuses Map (Identity Hash -> true/false)( true = viewable, false = unviewable)
|
|
// -map[[28]byte]bool: Profile hash statuses map (Profile Hash -> true/false)( true = viewable, false = unviewable)
|
|
// -error (returns err if input keys are invalid)
|
|
func ReadServerResponse_GetViewableStatuses(responseBytes []byte, connectionKey [32]byte)(bool, [16]byte, [16]byte, map[[16]byte]bool, map[[28]byte]bool, error){
|
|
|
|
ableToRead, requestIdentifier, hostIdentityHash, decryptedContentBytes, err := readEncryptedAndSignedResponse(responseBytes, connectionKey, "GetViewableStatuses")
|
|
if (err != nil) { return false, [16]byte{}, [16]byte{}, nil, nil, err }
|
|
if (ableToRead == false){
|
|
//Response is malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil, nil
|
|
}
|
|
|
|
type responseContentStruct struct{
|
|
IdentityHashStatuses map[[16]byte]bool
|
|
ProfileHashStatuses map[[28]byte]bool
|
|
}
|
|
|
|
var responseContentObject responseContentStruct
|
|
|
|
err = encoding.DecodeMessagePackBytes(true, decryptedContentBytes, &responseContentObject)
|
|
if (err != nil) {
|
|
// Response malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil, nil
|
|
}
|
|
|
|
identityHashStatusesMap := responseContentObject.IdentityHashStatuses
|
|
profileHashStatusesMap := responseContentObject.ProfileHashStatuses
|
|
|
|
//TODO: Verify maps
|
|
|
|
return true, requestIdentifier, hostIdentityHash, identityHashStatusesMap, profileHashStatusesMap, nil
|
|
}
|
|
|
|
|
|
//Outputs:
|
|
// -[]byte: Response bytes
|
|
// -error
|
|
func CreateServerResponse_BroadcastContent(hostPublicIdentityKey [32]byte, hostPrivateIdentityKey [64]byte, connectionKey [32]byte, requestIdentifier [16]byte, contentAcceptedInfoMap map[string]bool)([]byte, error){
|
|
|
|
//TODO: Verify inputs
|
|
|
|
type responseContentStruct struct{
|
|
HostIdentityKey [32]byte
|
|
RequestIdentifier [16]byte
|
|
ResponseType string
|
|
ContentAcceptedInfo map[string]bool //Content Hash -> true/false
|
|
}
|
|
|
|
responseContentObject := responseContentStruct{
|
|
HostIdentityKey: hostPublicIdentityKey,
|
|
RequestIdentifier: requestIdentifier,
|
|
ResponseType: "BroadcastContent",
|
|
ContentAcceptedInfo: contentAcceptedInfoMap,
|
|
}
|
|
|
|
innerResponseBytes, err := encoding.EncodeMessagePackBytes(responseContentObject)
|
|
if (err != nil) { return nil, err }
|
|
|
|
encryptedResponse, err := createEncryptedAndSignedResponse(connectionKey, hostPrivateIdentityKey, innerResponseBytes)
|
|
if (err != nil) { return nil, err }
|
|
|
|
return encryptedResponse, nil
|
|
}
|
|
|
|
|
|
//Outputs:
|
|
// -bool: Able to read server response
|
|
// -[16]byte: Request Identifier
|
|
// -[16]byte: Host Identity Hash
|
|
// -map[string]bool: Content Accepted Info Map (Content Hash -> true/false)
|
|
// -error (returns err if input keys are invalid)
|
|
func ReadServerResponse_BroadcastContent(responseBytes []byte, connectionKey [32]byte)(bool, [16]byte, [16]byte, map[string]bool, error){
|
|
|
|
//TODO: Verify stuff
|
|
|
|
ableToRead, requestIdentifier, hostIdentityHash, decryptedContentBytes, err := readEncryptedAndSignedResponse(responseBytes, connectionKey, "BroadcastContent")
|
|
if (err != nil) { return false, [16]byte{}, [16]byte{}, nil, err }
|
|
if (ableToRead == false){
|
|
//Response is malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
type responseContentStruct struct{
|
|
ContentAcceptedInfo map[string]bool
|
|
}
|
|
|
|
var responseContentObject responseContentStruct
|
|
|
|
err = encoding.DecodeMessagePackBytes(true, decryptedContentBytes, &responseContentObject)
|
|
if (err != nil) {
|
|
// Response is malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
contentAcceptedInfoMap := responseContentObject.ContentAcceptedInfo
|
|
|
|
for contentHash, _ := range contentAcceptedInfoMap{
|
|
|
|
_, err := helpers.GetContentTypeFromContentHash([]byte(contentHash))
|
|
if (err != nil){
|
|
// Invalid content hash
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
}
|
|
|
|
return true, requestIdentifier, hostIdentityHash, contentAcceptedInfoMap, nil
|
|
}
|
|
|
|
func createEncryptedAndSignedResponse(connectionKey [32]byte, hostPrivateIdentityKey [64]byte, innerResponseBytes []byte)([]byte, error){
|
|
|
|
responseSignedBytes, err := createResponseSignedContent(hostPrivateIdentityKey, innerResponseBytes)
|
|
if (err != nil) { return nil, err }
|
|
|
|
encryptedResponse, err := createEncryptedResponse(responseSignedBytes, connectionKey)
|
|
if (err != nil) { return nil, err }
|
|
|
|
return encryptedResponse, nil
|
|
}
|
|
|
|
//Outputs:
|
|
// -bool: Able to read (response is valid)
|
|
// -[16]byte: Request identifier
|
|
// -[16]byte: Host identity hash
|
|
// -[]byte: Content Bytes
|
|
// -error (return err if there is a bug in the function)
|
|
func readEncryptedAndSignedResponse(inputResponse []byte, connectionKey [32]byte, expectedResponseType string)(bool, [16]byte, [16]byte, []byte, error){
|
|
|
|
ableToDecrypt, decryptedResponseBytes, err := readEncryptedResponse(inputResponse, connectionKey)
|
|
if (err != nil) { return false, [16]byte{}, [16]byte{}, nil, err }
|
|
if (ableToDecrypt == false){
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
ableToRead, requestIdentifier, hostIdentityHash, contentBytes, err := readResponseSignedContent(decryptedResponseBytes, expectedResponseType)
|
|
if (err != nil) { return false, [16]byte{}, [16]byte{}, nil, err }
|
|
if (ableToRead == false){
|
|
//Response is malformed
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
return true, requestIdentifier, hostIdentityHash, contentBytes, nil
|
|
}
|
|
|
|
|
|
func createEncryptedResponse(contentToEncrypt []byte, connectionKey [32]byte)([]byte, error){
|
|
|
|
chaPolyNonce, err := helpers.GetNewRandom24ByteArray()
|
|
if (err != nil) { return nil, err }
|
|
|
|
cipheredContent, err := chaPolyShrink.EncryptChaPolyShrink(contentToEncrypt, connectionKey, chaPolyNonce, true, 100, false, [32]byte{})
|
|
if (err != nil) { return nil, err }
|
|
|
|
type encryptedResponseStruct struct{
|
|
ChaPolyNonce [24]byte
|
|
CipheredContent []byte
|
|
}
|
|
|
|
encryptedResponseObject := encryptedResponseStruct{
|
|
ChaPolyNonce: chaPolyNonce,
|
|
CipheredContent: cipheredContent,
|
|
}
|
|
|
|
encryptedResponseBytes, err := encoding.EncodeMessagePackBytes(encryptedResponseObject)
|
|
if (err != nil) { return nil, err }
|
|
|
|
return encryptedResponseBytes, nil
|
|
}
|
|
|
|
//Outputs:
|
|
// -bool: Response well formed and able to decrypt
|
|
// -[]byte: Decrypted response
|
|
// -error (decryption key inputs are malformed)
|
|
func readEncryptedResponse(inputResponse []byte, connectionKey [32]byte)(bool, []byte, error){
|
|
|
|
type encryptedResponseStruct struct{
|
|
ChaPolyNonce [24]byte
|
|
CipheredContent []byte
|
|
}
|
|
|
|
var encryptedResponseObject encryptedResponseStruct
|
|
|
|
err := encoding.DecodeMessagePackBytes(true, inputResponse, &encryptedResponseObject)
|
|
if (err != nil) {
|
|
return false, nil, nil
|
|
}
|
|
|
|
chaPolyNonce := encryptedResponseObject.ChaPolyNonce
|
|
cipheredContent := encryptedResponseObject.CipheredContent
|
|
|
|
ableToDecrypt, decryptedBytes, err := chaPolyShrink.DecryptChaPolyShrink(cipheredContent, connectionKey, chaPolyNonce, false, [32]byte{})
|
|
if (err != nil) {
|
|
return false, nil, nil
|
|
}
|
|
if (ableToDecrypt == false){
|
|
return false, nil, nil
|
|
}
|
|
|
|
return true, decryptedBytes, nil
|
|
}
|
|
|
|
|
|
func createResponseSignedContent(hostIdentityPrivateKey [64]byte, responseContent messagepack.RawMessage)([]byte, error){
|
|
|
|
contentHash, err := blake3.Get32ByteBlake3Hash(responseContent)
|
|
if (err != nil) { return nil, err }
|
|
|
|
responseSignature := edwardsKeys.CreateSignature(hostIdentityPrivateKey, contentHash)
|
|
|
|
type finalResponseStruct struct {
|
|
Signature [64]byte
|
|
Content messagepack.RawMessage
|
|
}
|
|
|
|
finalResponseObject := finalResponseStruct{
|
|
Signature: responseSignature,
|
|
Content: responseContent,
|
|
}
|
|
|
|
finalResponseBytes, err := encoding.EncodeMessagePackBytes(finalResponseObject)
|
|
if (err != nil) { return nil, err }
|
|
|
|
return finalResponseBytes, nil
|
|
}
|
|
|
|
//Outputs:
|
|
// -bool: Able to read (response is valid)
|
|
// -[16]byte: Request identifier
|
|
// -[16]byte: Host identity hash
|
|
// -[]byte: Content bytes
|
|
// -error (return err if there is a bug in the function)
|
|
func readResponseSignedContent(inputBytes []byte, expectedResponseType string)(bool, [16]byte, [16]byte, []byte, error){
|
|
|
|
type outerResponseStruct struct{
|
|
Signature [64]byte
|
|
Content messagepack.RawMessage
|
|
}
|
|
|
|
var outerResponseObject outerResponseStruct
|
|
|
|
err := encoding.DecodeMessagePackBytes(true, inputBytes, &outerResponseObject)
|
|
if (err != nil) {
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
responseSignature := outerResponseObject.Signature
|
|
responseContentBytes := outerResponseObject.Content
|
|
|
|
if (len(responseContentBytes) == 0){
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
responseContentHashed, err := blake3.Get32ByteBlake3Hash(responseContentBytes)
|
|
if (err != nil) { return false, [16]byte{}, [16]byte{}, nil, err }
|
|
|
|
type partialResponseStruct struct {
|
|
HostIdentityKey [32]byte
|
|
RequestIdentifier [16]byte
|
|
ResponseType string
|
|
}
|
|
|
|
var partialResponseObject partialResponseStruct
|
|
|
|
err = encoding.DecodeMessagePackBytes(true, responseContentBytes, &partialResponseObject)
|
|
if (err != nil) {
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
requestIdentifier := partialResponseObject.RequestIdentifier
|
|
hostIdentityKey := partialResponseObject.HostIdentityKey
|
|
responseType := partialResponseObject.ResponseType
|
|
|
|
isValid := edwardsKeys.VerifySignature(hostIdentityKey, responseSignature, responseContentHashed)
|
|
if (isValid == false){
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
hostIdentityHash, err := identity.ConvertIdentityKeyToIdentityHash(hostIdentityKey, "Host")
|
|
if (err != nil) { return false, [16]byte{}, [16]byte{}, nil, err }
|
|
|
|
if (responseType != expectedResponseType){
|
|
return false, [16]byte{}, [16]byte{}, nil, nil
|
|
}
|
|
|
|
return true, requestIdentifier, hostIdentityHash, responseContentBytes, nil
|
|
}
|
|
|
|
|
|
|