mirror of
https://github.com/ergochat/ergo.git
synced 2025-01-22 02:04:10 +01:00
77 lines
2.0 KiB
Go
77 lines
2.0 KiB
Go
|
package webpush
|
||
|
|
||
|
import (
|
||
|
"crypto/ecdh"
|
||
|
"crypto/ecdsa"
|
||
|
"crypto/elliptic"
|
||
|
"encoding/base64"
|
||
|
"fmt"
|
||
|
"math/big"
|
||
|
)
|
||
|
|
||
|
// ecdhPublicKeyToECDSA converts an ECDH key to an ECDSA key.
|
||
|
// This is deprecated as per https://github.com/golang/go/issues/63963
|
||
|
// but we need to do it in order to parse the legacy private key format.
|
||
|
func ecdhPublicKeyToECDSA(key *ecdh.PublicKey) (*ecdsa.PublicKey, error) {
|
||
|
rawKey := key.Bytes()
|
||
|
switch key.Curve() {
|
||
|
case ecdh.P256():
|
||
|
return &ecdsa.PublicKey{
|
||
|
Curve: elliptic.P256(),
|
||
|
X: big.NewInt(0).SetBytes(rawKey[1:33]),
|
||
|
Y: big.NewInt(0).SetBytes(rawKey[33:]),
|
||
|
}, nil
|
||
|
case ecdh.P384():
|
||
|
return &ecdsa.PublicKey{
|
||
|
Curve: elliptic.P384(),
|
||
|
X: big.NewInt(0).SetBytes(rawKey[1:49]),
|
||
|
Y: big.NewInt(0).SetBytes(rawKey[49:]),
|
||
|
}, nil
|
||
|
case ecdh.P521():
|
||
|
return &ecdsa.PublicKey{
|
||
|
Curve: elliptic.P521(),
|
||
|
X: big.NewInt(0).SetBytes(rawKey[1:67]),
|
||
|
Y: big.NewInt(0).SetBytes(rawKey[67:]),
|
||
|
}, nil
|
||
|
default:
|
||
|
return nil, fmt.Errorf("cannot convert non-NIST *ecdh.PublicKey to *ecdsa.PublicKey")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func ecdhPrivateKeyToECDSA(key *ecdh.PrivateKey) (*ecdsa.PrivateKey, error) {
|
||
|
// see https://github.com/golang/go/issues/63963
|
||
|
pubKey, err := ecdhPublicKeyToECDSA(key.PublicKey())
|
||
|
if err != nil {
|
||
|
return nil, fmt.Errorf("converting PublicKey part of *ecdh.PrivateKey: %w", err)
|
||
|
}
|
||
|
return &ecdsa.PrivateKey{
|
||
|
PublicKey: *pubKey,
|
||
|
D: big.NewInt(0).SetBytes(key.Bytes()),
|
||
|
}, nil
|
||
|
}
|
||
|
|
||
|
// DecodeLegacyVAPIDPrivateKey decodes the legacy string private key format
|
||
|
// returned by GenerateVAPIDKeys in v1.
|
||
|
func DecodeLegacyVAPIDPrivateKey(key string) (*VAPIDKeys, error) {
|
||
|
bytes, err := decodeSubscriptionKey(key)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
ecdhPrivKey, err := ecdh.P256().NewPrivateKey(bytes)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
ecdsaPrivKey, err := ecdhPrivateKeyToECDSA(ecdhPrivKey)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
publicKey := base64.RawURLEncoding.EncodeToString(ecdhPrivKey.PublicKey().Bytes())
|
||
|
return &VAPIDKeys{
|
||
|
privateKey: ecdsaPrivKey,
|
||
|
publicKey: publicKey,
|
||
|
}, nil
|
||
|
}
|