To verify that the messages shown actually were the one written at that specific time, you can manually decrypt the messages yourself. The actual algorithm is shown here.
func serializeAndCompress(msg Message) ([]byte, error) { // Include all necessary fields data := map[string]string{ "author": msg.Author, "header": msg.Header, "password": msg.Password, "createdDate": convertMillisToDateString(msg.WrittenDateMilli), "revealDate": convertMillisToDateString(msg.RevealDateMilli), "message": msg.Message, } jsonData, err := json.Marshal(data) if err != nil { return nil, err } // Compress the data var buf bytes.Buffer gz := gzip.NewWriter(&buf) if _, err := gz.Write(jsonData); err != nil { return nil, err } if err := gz.Close(); err != nil { return nil, err } return buf.Bytes(), nil } func encryptData(data []byte, password string) ([]byte, error) { // Derive a 32-byte key from the password key := sha256.Sum256([]byte(password)) // Create a new AES cipher using the key block, err := aes.NewCipher(key[:]) if err != nil { return nil, err } // Use AES in GCM mode aesGCM, err := cipher.NewGCM(block) if err != nil { return nil, err } // Generate a random nonce nonce := make([]byte, aesGCM.NonceSize()) if _, err := io.ReadFull(rand.Reader, nonce); err != nil { return nil, err } // Encrypt the data cipherText := aesGCM.Seal(nil, nonce, data, nil) // Combine nonce and ciphertext encryptedData := append(nonce, cipherText...) return encryptedData, nil } func encodeData(data []byte) string { return base64.URLEncoding.EncodeToString(data) } func CreatePublishableMessage(msg Message) (string, string, error) { // Serialize and compress the data compressedData, err := serializeAndCompress(msg) if err != nil { return "", "", err } // Encrypt the data encryptedData, err := encryptData(compressedData, msg.Password) if err != nil { return "", "", err } // Encode the encrypted data encodedData := encodeData(encryptedData) // Format the publishable message using msg.RevealDate publishableMessage := fmt.Sprintf("Time Message | Reveal time: %s | %s", convertMillisToDateString(msg.RevealDateMilli), encodedData) return publishableMessage, encodedData, nil } func DecryptPublishableMessage(encodedData, password string) (Message, error) { var msg Message // Decode the data encryptedData, err := decodeData(encodedData) if err != nil { return msg, err } // Decrypt the data compressedData, err := decryptData(encryptedData, password) if err != nil { return msg, err } // Decompress the data jsonData, err := decompressData(compressedData) if err != nil { return msg, err } // Deserialize the JSON if err := json.Unmarshal(jsonData, &msg); err != nil { return msg, err } return msg, nil } func decodeData(encodedData string) ([]byte, error) { return base64.URLEncoding.DecodeString(encodedData) } func decryptData(encryptedData []byte, password string) ([]byte, error) { key := sha256.Sum256([]byte(password)) block, err := aes.NewCipher(key[:]) if err != nil { return nil, err } aesGCM, err := cipher.NewGCM(block) if err != nil { return nil, err } nonceSize := aesGCM.NonceSize() if len(encryptedData) < nonceSize { return nil, fmt.Errorf("invalid encrypted data") } nonce, cipherText := encryptedData[:nonceSize], encryptedData[nonceSize:] data, err := aesGCM.Open(nil, nonce, cipherText, nil) if err != nil { return nil, err } return data, nil } func decompressData(data []byte) ([]byte, error) { buf := bytes.NewBuffer(data) gz, err := gzip.NewReader(buf) if err != nil { return nil, err } decompressedData, err := io.ReadAll(gz) if err != nil { return nil, err } if err := gz.Close(); err != nil { return nil, err } return decompressedData, nil } func generateRandomID(length int) (string, error) { const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" var result strings.Builder for i := 0; i < length; i++ { index, err := rand.Int(rand.Reader, big.NewInt(int64(len(charset)))) if err != nil { return "", err } result.WriteByte(charset[index.Int64()]) } return result.String(), nil } func convertMillisToDateString(milliseconds uint64) string { // Convert milliseconds to seconds and nanoseconds seconds := int64(milliseconds / 1000) nanoseconds := int64((milliseconds % 1000) * 1e6) // Create a time.Time object in UTC t := time.Unix(seconds, nanoseconds).UTC() // Format the time object to a readable string return t.Format("2006-01-02 15:04:05 UTC") }
Time Messages
Stated Today, Read Tomorrow