// inbox provides functions to read inboxes, create random inboxes, and to derive inboxes and sealer keys package inbox import "seekia/internal/cryptography/blake3" import "seekia/internal/encoding" import "seekia/internal/identity" import "crypto/rand" import "slices" import "errors" func GetNewRandomInbox()([10]byte, error){ var inboxArray [10]byte _, err := rand.Read(inboxArray[:]) if (err != nil) { return [10]byte{}, err } return inboxArray, nil } func GetNewRandomSecretInboxSeed()([22]byte, error){ var newSecretInboxSeed [22]byte _, err := rand.Read(newSecretInboxSeed[:]) if (err != nil) { return [22]byte{}, err } return newSecretInboxSeed, nil } func ReadInboxString(inputInbox string)([10]byte, error){ inboxBytes, err := encoding.DecodeBase32StringToBytes(inputInbox) if (err != nil){ return [10]byte{}, errors.New("ReadInboxString called with invalid inbox: " + inputInbox + ". Not Base32: " + err.Error()) } if (len(inboxBytes) != 10){ return [10]byte{}, errors.New("ReadInboxString called with invalid inbox: " + inputInbox + ". Invalid length.") } inboxArray := [10]byte(inboxBytes) return inboxArray, nil } func GetPublicInboxFromIdentityHash(inputIdentityHash [16]byte)([10]byte, error){ identityType, err := identity.GetIdentityTypeFromIdentityHash(inputIdentityHash) if (err != nil) { identityHashHex := encoding.EncodeBytesToHexString(inputIdentityHash[:]) return [10]byte{}, errors.New("GetPublicInboxFromIdentityHash called with invalid identity hash: " + identityHashHex) } if (identityType != "Mate" && identityType != "Moderator"){ return [10]byte{}, errors.New("GetPublicInboxFromIdentityHash called with Host identity hash.") } // This sequence of bytes is the string "identitypubinbox" decoded from base32 to bytes hashInputSuffix := []byte{64, 200, 217, 162, 120, 125, 2, 134, 133, 215} hashInput := slices.Concat(inputIdentityHash[:], hashInputSuffix) inboxBytes, err := blake3.GetBlake3HashAsBytes(10, hashInput) if (err != nil) { return [10]byte{}, err } inboxArray := [10]byte(inboxBytes) return inboxArray, nil } // Messages sent to a user's public inbox use a doublesealedkeys sealer key that is derived from the user's identity hash func GetPublicInboxSealerKeyFromIdentityHash(inputIdentityHash [16]byte)([32]byte, error){ identityType, err := identity.GetIdentityTypeFromIdentityHash(inputIdentityHash) if (err != nil) { inputIdentityHashHex := encoding.EncodeBytesToHexString(inputIdentityHash[:]) return [32]byte{}, errors.New("GetPublicInboxSealerKeyFromIdentityHash called with invalid identity hash: " + inputIdentityHashHex) } if (identityType != "Mate" && identityType != "Moderator"){ return [32]byte{}, errors.New("GetPublicInboxSealerKeyFromIdentityHash called with Host identityType identity hash.") } // This sequence of bytes is the string "identityhashpublicinboxsealerkey" decoded from base32 to bytes hashInputSuffix := []byte{64, 200, 217, 162, 120, 56, 36, 119, 208, 43, 64, 144, 208, 186, 242, 32, 22, 72, 168, 152} hashInput := slices.Concat(inputIdentityHash[:], hashInputSuffix) doubleSealedKeysSealerKey, err := blake3.GetBlake3HashAsBytes(32, hashInput) if (err != nil) { return [32]byte{}, err } doubleSealedKeysSealerKeyArray := [32]byte(doubleSealedKeysSealerKey) return doubleSealedKeysSealerKeyArray, nil } // Outputs: // -[10]byte: Secret inbox // -[32]byte: Secret inbox doubleSealedKeys sealer key // -error func GetSecretInboxAndSealerKeyFromSecretInboxSeed(inputSecretInboxSeed [22]byte)([10]byte, [32]byte, error){ secretInboxHashInput := append(inputSecretInboxSeed[:], 1) sealerKeyHashInput := append(inputSecretInboxSeed[:], 2) secretInbox, err := blake3.GetBlake3HashAsBytes(10, secretInboxHashInput) if (err != nil) { return [10]byte{}, [32]byte{}, err } secretInboxArray := [10]byte(secretInbox) sealerKey, err := blake3.GetBlake3HashAsBytes(32, sealerKeyHashInput) if (err != nil) { return [10]byte{}, [32]byte{}, err } sealerKeyArray := [32]byte(sealerKey) return secretInboxArray, sealerKeyArray, nil }