forked from jshiffer/matterbridge
96 lines
2.9 KiB
Go
96 lines
2.9 KiB
Go
|
// Package keyhelper is based on: https://github.com/WhisperSystems/libsignal-protocol-java/blob/master/java/src/main/java/org/whispersystems/libsignal/util/KeyHelper.java
|
||
|
package keyhelper
|
||
|
|
||
|
import (
|
||
|
"crypto/rand"
|
||
|
"encoding/binary"
|
||
|
"time"
|
||
|
|
||
|
"go.mau.fi/libsignal/ecc"
|
||
|
"go.mau.fi/libsignal/keys/identity"
|
||
|
"go.mau.fi/libsignal/state/record"
|
||
|
)
|
||
|
|
||
|
// GenerateIdentityKeyPair generates an identity keypair used for
|
||
|
// signing. Clients should only do this once at install time.
|
||
|
func GenerateIdentityKeyPair() (*identity.KeyPair, error) {
|
||
|
keyPair, err := ecc.GenerateKeyPair()
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
publicKey := identity.NewKey(keyPair.PublicKey())
|
||
|
return identity.NewKeyPair(publicKey, keyPair.PrivateKey()), nil
|
||
|
}
|
||
|
|
||
|
// GeneratePreKeys generates a list of PreKeys. Client shsould do this at
|
||
|
// install time, and subsequently any time the list of PreKeys stored on
|
||
|
// the server runs low.
|
||
|
//
|
||
|
// PreKeys IDs are shorts, so they will eventually be repeated. Clients
|
||
|
// should store PreKeys in a circular buffer, so that they are repeated
|
||
|
// as infrequently as possible.
|
||
|
func GeneratePreKeys(start int, count int, serializer record.PreKeySerializer) ([]*record.PreKey, error) {
|
||
|
var preKeys []*record.PreKey
|
||
|
|
||
|
for i := start; i <= count; i++ {
|
||
|
key, err := ecc.GenerateKeyPair()
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
preKeys = append(preKeys, record.NewPreKey(uint32(i), key, serializer))
|
||
|
}
|
||
|
|
||
|
return preKeys, nil
|
||
|
}
|
||
|
|
||
|
// GenerateLastResortKey will generate the last resort PreKey. Clients should
|
||
|
// do this only once, at install time, and durably store it for the length
|
||
|
// of the install.
|
||
|
func GenerateLastResortKey(serializer record.PreKeySerializer) (*record.PreKey, error) {
|
||
|
keyPair, err := ecc.GenerateKeyPair()
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
return record.NewPreKey(0, keyPair, serializer), nil
|
||
|
}
|
||
|
|
||
|
// GenerateSignedPreKey generates a signed PreKey.
|
||
|
func GenerateSignedPreKey(identityKeyPair *identity.KeyPair, signedPreKeyID uint32, serializer record.SignedPreKeySerializer) (*record.SignedPreKey, error) {
|
||
|
keyPair, err := ecc.GenerateKeyPair()
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
signature := ecc.CalculateSignature(identityKeyPair.PrivateKey(), keyPair.PublicKey().Serialize())
|
||
|
timestamp := time.Now().Unix()
|
||
|
|
||
|
return record.NewSignedPreKey(signedPreKeyID, timestamp, keyPair, signature, serializer), nil
|
||
|
}
|
||
|
|
||
|
// GenerateRegistrationID generates a registration ID. Clients should only do
|
||
|
// this once, at install time.
|
||
|
func GenerateRegistrationID() uint32 {
|
||
|
var n uint32
|
||
|
binary.Read(rand.Reader, binary.LittleEndian, &n)
|
||
|
|
||
|
return n
|
||
|
}
|
||
|
|
||
|
//---------- Group Stuff ----------------
|
||
|
|
||
|
func GenerateSenderSigningKey() (*ecc.ECKeyPair, error) {
|
||
|
return ecc.GenerateKeyPair()
|
||
|
}
|
||
|
|
||
|
func GenerateSenderKey() []byte {
|
||
|
randBytes := make([]byte, 32)
|
||
|
rand.Read(randBytes)
|
||
|
return randBytes
|
||
|
}
|
||
|
|
||
|
func GenerateSenderKeyID() uint32 {
|
||
|
return GenerateRegistrationID()
|
||
|
}
|
||
|
|
||
|
//---------- End Group Stuff --------------
|