matrix-prometheus/vendor/maunium.net/go/mautrix/crypto/verification_sas_methods.go

205 lines
5.6 KiB
Go

// Copyright (c) 2020 Nikos Filippakis
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//go:build !nosas
// +build !nosas
package crypto
import (
"fmt"
"maunium.net/go/mautrix/crypto/olm"
"maunium.net/go/mautrix/event"
"maunium.net/go/mautrix/id"
)
// SASData contains the data that users need to verify.
type SASData interface {
Type() event.SASMethod
}
// VerificationMethod describes a method for generating a SAS.
type VerificationMethod interface {
// GetVerificationSAS uses the user, device ID and key of the user who initiated the verification transaction,
// the user, device ID and key of the user who accepted, the transaction ID and the SAS object to generate a SAS.
// The SAS can be any type, such as an array of numbers or emojis.
GetVerificationSAS(initUserID id.UserID, initDeviceID id.DeviceID, initKey string,
acceptUserID id.UserID, acceptDeviceID id.DeviceID, acceptKey string,
transactionID string, sas *olm.SAS) (SASData, error)
// Type returns the type of this SAS method
Type() event.SASMethod
}
const sasInfoFormat = "MATRIX_KEY_VERIFICATION_SAS|%s|%s|%s|%s|%s|%s|%s"
// VerificationMethodDecimal describes the decimal SAS method.
type VerificationMethodDecimal struct{}
// DecimalSASData contains the verification numbers for the decimal SAS method.
type DecimalSASData [3]uint
// Type returns the decimal SAS method type.
func (DecimalSASData) Type() event.SASMethod {
return event.SASDecimal
}
// GetVerificationSAS generates the three numbers that need to match with the other device for a verification to be valid.
func (VerificationMethodDecimal) GetVerificationSAS(initUserID id.UserID, initDeviceID id.DeviceID, initKey string,
acceptUserID id.UserID, acceptDeviceID id.DeviceID, acceptKey string,
transactionID string, sas *olm.SAS) (SASData, error) {
sasInfo := fmt.Sprintf(sasInfoFormat,
initUserID, initDeviceID, initKey,
acceptUserID, acceptDeviceID, acceptKey,
transactionID)
sasBytes, err := sas.GenerateBytes([]byte(sasInfo), 5)
if err != nil {
return DecimalSASData{0, 0, 0}, err
}
numbers := DecimalSASData{
(uint(sasBytes[0])<<5 | uint(sasBytes[1])>>3) + 1000,
(uint(sasBytes[1]&0x7)<<10 | uint(sasBytes[2])<<2 | uint(sasBytes[3]>>6)) + 1000,
(uint(sasBytes[3]&0x3F)<<7 | uint(sasBytes[4])>>1) + 1000,
}
return numbers, nil
}
// Type returns the decimal SAS method type.
func (VerificationMethodDecimal) Type() event.SASMethod {
return event.SASDecimal
}
var allEmojis = [...]VerificationEmoji{
{'🐶', "Dog"},
{'🐱', "Cat"},
{'🦁', "Lion"},
{'🐎', "Horse"},
{'🦄', "Unicorn"},
{'🐷', "Pig"},
{'🐘', "Elephant"},
{'🐰', "Rabbit"},
{'🐼', "Panda"},
{'🐓', "Rooster"},
{'🐧', "Penguin"},
{'🐢', "Turtle"},
{'🐟', "Fish"},
{'🐙', "Octopus"},
{'🦋', "Butterfly"},
{'🌷', "Flower"},
{'🌳', "Tree"},
{'🌵', "Cactus"},
{'🍄', "Mushroom"},
{'🌏', "Globe"},
{'🌙', "Moon"},
{'☁', "Cloud"},
{'🔥', "Fire"},
{'🍌', "Banana"},
{'🍎', "Apple"},
{'🍓', "Strawberry"},
{'🌽', "Corn"},
{'🍕', "Pizza"},
{'🎂', "Cake"},
{'❤', "Heart"},
{'😀', "Smiley"},
{'🤖', "Robot"},
{'🎩', "Hat"},
{'👓', "Glasses"},
{'🔧', "Spanner"},
{'🎅', "Santa"},
{'👍', "Thumbs Up"},
{'☂', "Umbrella"},
{'⌛', "Hourglass"},
{'⏰', "Clock"},
{'🎁', "Gift"},
{'💡', "Light Bulb"},
{'📕', "Book"},
{'✏', "Pencil"},
{'📎', "Paperclip"},
{'✂', "Scissors"},
{'🔒', "Lock"},
{'🔑', "Key"},
{'🔨', "Hammer"},
{'☎', "Telephone"},
{'🏁', "Flag"},
{'🚂', "Train"},
{'🚲', "Bicycle"},
{'✈', "Aeroplane"},
{'🚀', "Rocket"},
{'🏆', "Trophy"},
{'⚽', "Ball"},
{'🎸', "Guitar"},
{'🎺', "Trumpet"},
{'🔔', "Bell"},
{'⚓', "Anchor"},
{'🎧', "Headphones"},
{'📁', "Folder"},
{'📌', "Pin"},
}
// VerificationEmoji describes an emoji that might be sent for verifying devices.
type VerificationEmoji struct {
Emoji rune
Description string
}
func (vm VerificationEmoji) GetEmoji() rune {
return vm.Emoji
}
func (vm VerificationEmoji) GetDescription() string {
return vm.Description
}
// EmojiSASData contains the verification emojis for the emoji SAS method.
type EmojiSASData [7]VerificationEmoji
// Type returns the emoji SAS method type.
func (EmojiSASData) Type() event.SASMethod {
return event.SASEmoji
}
// VerificationMethodEmoji describes the emoji SAS method.
type VerificationMethodEmoji struct{}
// GetVerificationSAS generates the three numbers that need to match with the other device for a verification to be valid.
func (VerificationMethodEmoji) GetVerificationSAS(initUserID id.UserID, initDeviceID id.DeviceID, initKey string,
acceptUserID id.UserID, acceptDeviceID id.DeviceID, acceptKey string,
transactionID string, sas *olm.SAS) (SASData, error) {
sasInfo := fmt.Sprintf(sasInfoFormat,
initUserID, initDeviceID, initKey,
acceptUserID, acceptDeviceID, acceptKey,
transactionID)
var emojis EmojiSASData
sasBytes, err := sas.GenerateBytes([]byte(sasInfo), 6)
if err != nil {
return emojis, err
}
sasNum := uint64(sasBytes[0])<<40 | uint64(sasBytes[1])<<32 | uint64(sasBytes[2])<<24 |
uint64(sasBytes[3])<<16 | uint64(sasBytes[4])<<8 | uint64(sasBytes[5])
for i := 0; i < len(emojis); i++ {
// take nth group of 6 bits
emojiIdx := (sasNum >> uint(48-(i+1)*6)) & 0x3F
emoji := allEmojis[emojiIdx]
emojis[i] = emoji
}
return emojis, nil
}
// Type returns the emoji SAS method type.
func (VerificationMethodEmoji) Type() event.SASMethod {
return event.SASEmoji
}