127 lines
4.4 KiB
Go
127 lines
4.4 KiB
Go
package licence
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/ed25519"
|
|
"encoding/json"
|
|
"fmt"
|
|
"unicode/utf8"
|
|
)
|
|
|
|
type SigningKeyCertificate struct {
|
|
FormatVersion int `json:"format_version"`
|
|
KeyID string `json:"key_id"`
|
|
PublicKey string `json:"public_key"`
|
|
RootSignature string `json:"root_signature"`
|
|
}
|
|
|
|
type Envelope struct {
|
|
FormatVersion int `json:"format_version"`
|
|
Licence Claims `json:"licence"`
|
|
SigningKeyCertificate SigningKeyCertificate `json:"signing_key_certificate"`
|
|
Signature string `json:"signature"`
|
|
}
|
|
|
|
func Parse(content []byte) (Envelope, error) {
|
|
var envelope Envelope
|
|
if len(content) > maximumLicenceFileBytes {
|
|
return envelope, ErrFileTooLarge
|
|
}
|
|
if err := strictDecodeJSON(content, &envelope); err != nil {
|
|
return envelope, fmt.Errorf("%w: %v", ErrMalformedFile, err)
|
|
}
|
|
if err := validateEnvelopeFormat(envelope); err != nil {
|
|
return envelope, err
|
|
}
|
|
return envelope, nil
|
|
}
|
|
|
|
func MarshalEnvelope(envelope Envelope) ([]byte, error) {
|
|
if err := validateEnvelopeFormat(envelope); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var output bytes.Buffer
|
|
encoder := json.NewEncoder(&output)
|
|
encoder.SetEscapeHTML(false)
|
|
encoder.SetIndent("", " ")
|
|
if err := encoder.Encode(envelope); err != nil {
|
|
return nil, fmt.Errorf("编码许可证文件: %w", err)
|
|
}
|
|
if output.Len() > maximumLicenceFileBytes {
|
|
return nil, ErrFileTooLarge
|
|
}
|
|
return output.Bytes(), nil
|
|
}
|
|
|
|
func RootPublicKey() ed25519.PublicKey {
|
|
publicKey := make(ed25519.PublicKey, len(rootPublicKey))
|
|
copy(publicKey, rootPublicKey[:])
|
|
return publicKey
|
|
}
|
|
|
|
func VerifySigningKeyCertificate(c SigningKeyCertificate) (ed25519.PublicKey, error) {
|
|
if c.FormatVersion != formatVersion {
|
|
return nil, fmt.Errorf("%w: 格式版本错误", ErrInvalidKeyCertificate)
|
|
}
|
|
if _, err := parseUUID(c.KeyID); err != nil {
|
|
return nil, fmt.Errorf("%w: 密钥 ID 格式错误", ErrInvalidKeyCertificate)
|
|
}
|
|
publicKey, err := decodeBase64URL(c.PublicKey, ed25519.PublicKeySize)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("%w: 公钥格式错误", ErrInvalidKeyCertificate)
|
|
}
|
|
rootSignature, err := decodeBase64URL(c.RootSignature, ed25519.SignatureSize)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("%w: 根签名格式错误", ErrInvalidKeyCertificate)
|
|
}
|
|
message, err := CertificateMessage(c)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("%w: 凭证消息格式错误", ErrInvalidKeyCertificate)
|
|
}
|
|
if !ed25519.Verify(rootPublicKey[:], message, rootSignature) {
|
|
return nil, fmt.Errorf("%w: 根签名验证失败", ErrInvalidKeyCertificate)
|
|
}
|
|
|
|
result := make(ed25519.PublicKey, len(publicKey))
|
|
copy(result, publicKey)
|
|
return result, nil
|
|
}
|
|
|
|
func validateEnvelopeFormat(envelope Envelope) error {
|
|
if envelope.FormatVersion != formatVersion || envelope.SigningKeyCertificate.FormatVersion != formatVersion {
|
|
return ErrUnsupportedVersion
|
|
}
|
|
if _, err := parseUUID(envelope.Licence.ID); err != nil {
|
|
return fmt.Errorf("%w: 许可证 ID 格式错误", ErrMalformedFile)
|
|
}
|
|
if _, err := parseUUID(envelope.Licence.SigningKeyID); err != nil {
|
|
return fmt.Errorf("%w: 签发密钥 ID 格式错误", ErrMalformedFile)
|
|
}
|
|
if _, err := parseUUID(envelope.SigningKeyCertificate.KeyID); err != nil {
|
|
return fmt.Errorf("%w: 凭证密钥 ID 格式错误", ErrMalformedFile)
|
|
}
|
|
if !utf8.ValidString(envelope.Licence.PlatformName) || !utf8.ValidString(envelope.Licence.Workspace) {
|
|
return fmt.Errorf("%w: 主体字符串不是有效的 UTF-8", ErrMalformedFile)
|
|
}
|
|
if _, err := envelope.Licence.IssuedOn.Time(); err != nil {
|
|
return fmt.Errorf("%w: 签发日期格式错误", ErrMalformedFile)
|
|
}
|
|
if _, err := envelope.Licence.ValidFrom.Time(); err != nil {
|
|
return fmt.Errorf("%w: 生效日期格式错误", ErrMalformedFile)
|
|
}
|
|
if _, err := envelope.Licence.ExpiresOn.Time(); err != nil {
|
|
return fmt.Errorf("%w: 到期日期格式错误", ErrMalformedFile)
|
|
}
|
|
if _, err := decodeBase64URL(envelope.SigningKeyCertificate.PublicKey, ed25519.PublicKeySize); err != nil {
|
|
return fmt.Errorf("%w: 凭证公钥格式错误", ErrMalformedFile)
|
|
}
|
|
if _, err := decodeBase64URL(envelope.SigningKeyCertificate.RootSignature, ed25519.SignatureSize); err != nil {
|
|
return fmt.Errorf("%w: 根签名格式错误", ErrMalformedFile)
|
|
}
|
|
if _, err := decodeBase64URL(envelope.Signature, ed25519.SignatureSize); err != nil {
|
|
return fmt.Errorf("%w: 许可证签名格式错误", ErrMalformedFile)
|
|
}
|
|
return nil
|
|
}
|