seekia/internal/moderation/readReports/readReports.go

302 lines
8.2 KiB
Go

// readReports provides functions to read reports.
package readReports
import "seekia/internal/allowedText"
import "seekia/internal/cryptography/blake3"
import "seekia/internal/encoding"
import "seekia/internal/helpers"
import messagepack "github.com/vmihailenco/msgpack/v5"
import "errors"
func VerifyReport(inputReport []byte)(bool, error){
ableToRead, _, _, _, _, _, _, err := ReadReport(true, inputReport)
if (err != nil){
return false, err
}
if (ableToRead == false){
return false, nil
}
return true, nil
}
// This is used to verify report hashes
func VerifyReportHash(inputHash [30]byte, reportTypeProvided bool, expectedReportType string)(bool, error){
if (reportTypeProvided == true){
if (expectedReportType != "Identity" && expectedReportType != "Profile" && expectedReportType != "Attribute" && expectedReportType != "Message"){
return false, errors.New("VerifyReportHash called with invalid expectedReportType: " + expectedReportType)
}
}
reportType, err := GetReportTypeFromReportHash(inputHash)
if (err != nil){
return false, nil
}
if (reportTypeProvided == true){
if (reportType != expectedReportType){
return false, nil
}
}
return true, nil
}
func GetReportTypeFromReportHash(inputHash [30]byte)(string, error){
metadataByte := inputHash[29]
if (metadataByte == 1){
return "Identity", nil
}
if (metadataByte == 2){
return "Profile", nil
}
if (metadataByte == 3){
return "Attribute", nil
}
if (metadataByte == 4){
return "Message", nil
}
reportHashHex := encoding.EncodeBytesToHexString(inputHash[:])
return "", errors.New("GetReportTypeFromReportHash called with invalid reportHash: " + reportHashHex)
}
// This function computes the report hash and returns it
//Outputs:
// -bool: Able to read
// -[30]byte: Report Hash
// -int: Report Version
// -byte: Network Type (1 == Mainnet, 2 == Testnet1)
// -int64: Broadcast Time (alleged, could be fake, like all broadcast times)
// -string: Report Type
// -[]byte: Reported Hash
// -map[string]string: Report map
// -error
func ReadReportAndHash(verifyReport bool, inputReport []byte)(bool, [30]byte, int, byte, int64, string, []byte, map[string]string, error){
ableToRead, reportVersion, reportNetworkType, reportBroadcastTime, reportType, reportedHash, reportMap, err := ReadReport(verifyReport, inputReport)
if (err != nil){ return false, [30]byte{}, 0, 0, 0, "", nil, nil, err }
if (ableToRead == false){
return false, [30]byte{}, 0, 0, 0, "", nil, nil, nil
}
reportHashWithoutMetadataByte, err := blake3.GetBlake3HashAsBytes(29, inputReport)
if (err != nil){ return false, [30]byte{}, 0, 0, 0, "", nil, nil, err }
getReportHashMetadataByte := func()(byte, error){
if (reportType == "Identity"){
return 1, nil
}
if (reportType == "Profile"){
return 2, nil
}
if (reportType == "Attribute"){
return 3, nil
}
if (reportType == "Message"){
return 4, nil
}
return 0, errors.New("ReadReport returning invalid reportType: " + reportType)
}
reportHashMetadataByte, err := getReportHashMetadataByte()
if (err != nil){ return false, [30]byte{}, 0, 0, 0, "", nil, nil, err }
reportHashSlice := append(reportHashWithoutMetadataByte, reportHashMetadataByte)
reportHash := [30]byte(reportHashSlice)
return true, reportHash, reportVersion, reportNetworkType, reportBroadcastTime, reportType, reportedHash, reportMap, nil
}
// This function does not compute the report hash, thus it is faster
//Outputs:
// -bool: Able to read
// -int: Report Version
// -byte: Network Type (1 == Mainnet, 2 == Testnet1)
// -int64: Broadcast Time (alleged, could be fake, like all broadcast times)
// -string: Report Type
// -[]byte: Reported Hash
// -map[string]string: Report map
// -error
func ReadReport(verifyReport bool, inputReport []byte)(bool, int, byte, int64, string, []byte, map[string]string, error){
reportContentMap := make(map[int]messagepack.RawMessage)
err := messagepack.Unmarshal(inputReport, &reportContentMap)
if (err != nil) {
// Invalid Report: Invalid Messagepack
return false, 0, 0, 0, "", nil, nil, nil
}
reportVersionMessagepack, exists := reportContentMap[1]
if (exists == false){
// Invalid Report: Missing ReportVersion
return false, 0, 0, 0, "", nil, nil, nil
}
reportVersion, err := encoding.DecodeRawMessagePackToInt(reportVersionMessagepack)
if (err != nil) {
// Invalid Report: Invalid report version
return false, 0, 0, 0, "", nil, nil, nil
}
if (reportVersion != 1){
// We cannot read this report. It was created by a newer version of Seekia.
return false, 0, 0, 0, "", nil, nil, nil
}
networkTypeMessagepack, exists := reportContentMap[2]
if (exists == false){
// Invalid Report: Missing NetworkType
return false, 0, 0, 0, "", nil, nil, nil
}
reportNetworkType, err := encoding.DecodeRawMessagePackToByte(networkTypeMessagepack)
if (err != nil) {
// Invalid Report: Invalid NetworkType
return false, 0, 0, 0, "", nil, nil, nil
}
isValid := helpers.VerifyNetworkType(reportNetworkType)
if (isValid == false){
// Invalid Report: Invalid NetworkType
return false, 0, 0, 0, "", nil, nil, nil
}
broadcastTimeMessagepack, exists := reportContentMap[3]
if (exists == false){
// Invalid Report: Missing BroadcastTime
return false, 0, 0, 0, "", nil, nil, nil
}
broadcastTime, err := encoding.DecodeRawMessagePackToInt64(broadcastTimeMessagepack)
if (err != nil) {
// Invalid Report: Invalid BroadcastTime
return false, 0, 0, 0, "", nil, nil, nil
}
reportedHashMessagepack, exists := reportContentMap[4]
if (exists == false){
// Invalid Report: Missing ReportedHash
return false, 0, 0, 0, "", nil, nil, nil
}
reportedHash, err := encoding.DecodeRawMessagePackToBytes(reportedHashMessagepack)
if (err != nil) {
// Invalid Report: Invalid ReportedHash
return false, 0, 0, 0, "", nil, nil, nil
}
reportType, err := helpers.GetReportedTypeFromReportedHash(reportedHash)
if (err != nil){
// Invalid Report: Invalid ReportedHash
return false, 0, 0, 0, "", nil, nil, nil
}
// These variables are only included in some reports
var reason string
var messageCipherKeyBytes []byte
reasonMessagepack, exists := reportContentMap[5]
if (exists == true){
err = messagepack.Unmarshal(reasonMessagepack, &reason)
if (err != nil) {
// Invalid Report: Invalid Reason
return false, 0, 0, 0, "", nil, nil, nil
}
}
if (reportType == "Message"){
messageCipherKeyMessagepack, exists := reportContentMap[6]
if (exists == false){
// Invalid Report: Missing MessageCipherKey
return false, 0, 0, 0, "", nil, nil, nil
}
err = messagepack.Unmarshal(messageCipherKeyMessagepack, &messageCipherKeyBytes)
if (err != nil) {
// Invalid Report: Invalid Reason
return false, 0, 0, 0, "", nil, nil, nil
}
}
if (verifyReport == true){
isValid := helpers.VerifyBroadcastTime(broadcastTime)
if (isValid == false){
// Invalid report: Invalid broadcast time
return false, 0, 0, 0, "", nil, nil, nil
}
if (reportType == "Message"){
if (len(messageCipherKeyBytes) != 32){
// Invalid Report: Report contains invalid messageCipherKey
return false, 0, 0, 0, "", nil, nil, nil
}
}
if (reason != "") {
if (len(reason) > 200) {
// Invalid report: Report contains invalid reason
return false, 0, 0, 0, "", nil, nil, nil
}
isAllowed := allowedText.VerifyStringIsAllowed(reason)
if (isAllowed == false){
// Invalid report: Report contains invalid reason
return false, 0, 0, 0, "", nil, nil, nil
}
}
}
reportVersionString := helpers.ConvertIntToString(reportVersion)
reportNetworkTypeString := helpers.ConvertByteToString(reportNetworkType)
broadcastTimeString := helpers.ConvertInt64ToString(broadcastTime)
reportedHashString, err := helpers.EncodeReportedHashBytesToString(reportedHash)
if (err != nil) { return false, 0, 0, 0, "", nil, nil, err }
reportMap := map[string]string{
"ReportVersion": reportVersionString,
"NetworkType": reportNetworkTypeString,
"BroadcastTime": broadcastTimeString,
"ReportedHash": reportedHashString,
}
if (reportType == "Message"){
messageCipherKey := encoding.EncodeBytesToHexString(messageCipherKeyBytes)
reportMap["MessageCipherKey"] = messageCipherKey
}
if (reason != ""){
reportMap["Reason"] = reason
}
return true, 1, reportNetworkType, broadcastTime, reportType, reportedHash, reportMap, nil
}