github.com/Lephar/snapd@v0.0.0-20210825215435-c7fba9cef4d2/asserts/crypto.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2015-2016 Canonical Ltd 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 3 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package asserts 21 22 import ( 23 "bytes" 24 "crypto" 25 "crypto/rand" 26 "crypto/rsa" 27 28 // be explicit about supporting SHA256 29 _ "crypto/sha256" 30 31 // be explicit about needing SHA512 32 _ "crypto/sha512" 33 "encoding/base64" 34 "fmt" 35 "io" 36 "time" 37 38 "golang.org/x/crypto/openpgp/packet" 39 "golang.org/x/crypto/sha3" 40 ) 41 42 const ( 43 maxEncodeLineLength = 76 44 v1 = 0x1 45 ) 46 47 var ( 48 v1Header = []byte{v1} 49 v1FixedTimestamp = time.Date(2016, time.January, 1, 0, 0, 0, 0, time.UTC) 50 ) 51 52 func encodeV1(data []byte) []byte { 53 buf := new(bytes.Buffer) 54 buf.Grow(base64.StdEncoding.EncodedLen(len(data) + 1)) 55 enc := base64.NewEncoder(base64.StdEncoding, buf) 56 enc.Write(v1Header) 57 enc.Write(data) 58 enc.Close() 59 flat := buf.Bytes() 60 flatSize := len(flat) 61 62 buf = new(bytes.Buffer) 63 buf.Grow(flatSize + flatSize/maxEncodeLineLength + 1) 64 off := 0 65 for { 66 endOff := off + maxEncodeLineLength 67 if endOff > flatSize { 68 endOff = flatSize 69 } 70 buf.Write(flat[off:endOff]) 71 off = endOff 72 if off >= flatSize { 73 break 74 } 75 buf.WriteByte('\n') 76 } 77 78 return buf.Bytes() 79 } 80 81 type keyEncoder interface { 82 keyEncode(w io.Writer) error 83 } 84 85 func encodeKey(key keyEncoder, kind string) ([]byte, error) { 86 buf := new(bytes.Buffer) 87 err := key.keyEncode(buf) 88 if err != nil { 89 return nil, fmt.Errorf("cannot encode %s: %v", kind, err) 90 } 91 return encodeV1(buf.Bytes()), nil 92 } 93 94 type openpgpSigner interface { 95 sign(content []byte) (*packet.Signature, error) 96 } 97 98 func signContent(content []byte, privateKey PrivateKey) ([]byte, error) { 99 signer, ok := privateKey.(openpgpSigner) 100 if !ok { 101 panic(fmt.Errorf("not an internally supported PrivateKey: %T", privateKey)) 102 } 103 104 sig, err := signer.sign(content) 105 if err != nil { 106 return nil, err 107 } 108 109 buf := new(bytes.Buffer) 110 err = sig.Serialize(buf) 111 if err != nil { 112 return nil, err 113 } 114 115 return encodeV1(buf.Bytes()), nil 116 } 117 118 func decodeV1(b []byte, kind string) (packet.Packet, error) { 119 if len(b) == 0 { 120 return nil, fmt.Errorf("cannot decode %s: no data", kind) 121 } 122 buf := make([]byte, base64.StdEncoding.DecodedLen(len(b))) 123 n, err := base64.StdEncoding.Decode(buf, b) 124 if err != nil { 125 return nil, fmt.Errorf("cannot decode %s: %v", kind, err) 126 } 127 if n == 0 { 128 return nil, fmt.Errorf("cannot decode %s: base64 without data", kind) 129 } 130 buf = buf[:n] 131 if buf[0] != v1 { 132 return nil, fmt.Errorf("unsupported %s format version: %d", kind, buf[0]) 133 } 134 rd := bytes.NewReader(buf[1:]) 135 pkt, err := packet.Read(rd) 136 if err != nil { 137 return nil, fmt.Errorf("cannot decode %s: %v", kind, err) 138 } 139 if rd.Len() != 0 { 140 return nil, fmt.Errorf("%s has spurious trailing data", kind) 141 } 142 return pkt, nil 143 } 144 145 func decodeSignature(signature []byte) (*packet.Signature, error) { 146 pkt, err := decodeV1(signature, "signature") 147 if err != nil { 148 return nil, err 149 } 150 sig, ok := pkt.(*packet.Signature) 151 if !ok { 152 return nil, fmt.Errorf("expected signature, got instead: %T", pkt) 153 } 154 return sig, nil 155 } 156 157 // PublicKey is the public part of a cryptographic private/public key pair. 158 type PublicKey interface { 159 // ID returns the id of the key used for lookup. 160 ID() string 161 162 // verify verifies signature is valid for content using the key. 163 verify(content []byte, sig *packet.Signature) error 164 165 keyEncoder 166 } 167 168 type openpgpPubKey struct { 169 pubKey *packet.PublicKey 170 sha3_384 string 171 } 172 173 func (opgPubKey *openpgpPubKey) ID() string { 174 return opgPubKey.sha3_384 175 } 176 177 func (opgPubKey *openpgpPubKey) verify(content []byte, sig *packet.Signature) error { 178 h := sig.Hash.New() 179 h.Write(content) 180 return opgPubKey.pubKey.VerifySignature(h, sig) 181 } 182 183 func (opgPubKey openpgpPubKey) keyEncode(w io.Writer) error { 184 return opgPubKey.pubKey.Serialize(w) 185 } 186 187 func newOpenPGPPubKey(intPubKey *packet.PublicKey) *openpgpPubKey { 188 h := sha3.New384() 189 h.Write(v1Header) 190 err := intPubKey.Serialize(h) 191 if err != nil { 192 panic("internal error: cannot compute public key sha3-384") 193 } 194 sha3_384, err := EncodeDigest(crypto.SHA3_384, h.Sum(nil)) 195 if err != nil { 196 panic("internal error: cannot compute public key sha3-384") 197 } 198 return &openpgpPubKey{pubKey: intPubKey, sha3_384: sha3_384} 199 } 200 201 // RSAPublicKey returns a database useable public key out of rsa.PublicKey. 202 func RSAPublicKey(pubKey *rsa.PublicKey) PublicKey { 203 intPubKey := packet.NewRSAPublicKey(v1FixedTimestamp, pubKey) 204 return newOpenPGPPubKey(intPubKey) 205 } 206 207 // DecodePublicKey deserializes a public key. 208 func DecodePublicKey(pubKey []byte) (PublicKey, error) { 209 pkt, err := decodeV1(pubKey, "public key") 210 if err != nil { 211 return nil, err 212 } 213 pubk, ok := pkt.(*packet.PublicKey) 214 if !ok { 215 return nil, fmt.Errorf("expected public key, got instead: %T", pkt) 216 } 217 rsaPubKey, ok := pubk.PublicKey.(*rsa.PublicKey) 218 if !ok { 219 return nil, fmt.Errorf("expected RSA public key, got instead: %T", pubk.PublicKey) 220 } 221 return RSAPublicKey(rsaPubKey), nil 222 } 223 224 // EncodePublicKey serializes a public key, typically for embedding in an assertion. 225 func EncodePublicKey(pubKey PublicKey) ([]byte, error) { 226 return encodeKey(pubKey, "public key") 227 } 228 229 // PrivateKey is a cryptographic private/public key pair. 230 type PrivateKey interface { 231 // PublicKey returns the public part of the pair. 232 PublicKey() PublicKey 233 234 keyEncoder 235 } 236 237 type openpgpPrivateKey struct { 238 privk *packet.PrivateKey 239 } 240 241 func (opgPrivK openpgpPrivateKey) PublicKey() PublicKey { 242 return newOpenPGPPubKey(&opgPrivK.privk.PublicKey) 243 } 244 245 func (opgPrivK openpgpPrivateKey) keyEncode(w io.Writer) error { 246 return opgPrivK.privk.Serialize(w) 247 } 248 249 var openpgpConfig = &packet.Config{ 250 DefaultHash: crypto.SHA512, 251 } 252 253 func (opgPrivK openpgpPrivateKey) sign(content []byte) (*packet.Signature, error) { 254 privk := opgPrivK.privk 255 sig := new(packet.Signature) 256 sig.PubKeyAlgo = privk.PubKeyAlgo 257 sig.Hash = openpgpConfig.Hash() 258 sig.CreationTime = time.Now() 259 260 h := openpgpConfig.Hash().New() 261 h.Write(content) 262 263 err := sig.Sign(h, privk, openpgpConfig) 264 if err != nil { 265 return nil, err 266 } 267 268 return sig, nil 269 } 270 271 func decodePrivateKey(privKey []byte) (PrivateKey, error) { 272 pkt, err := decodeV1(privKey, "private key") 273 if err != nil { 274 return nil, err 275 } 276 privk, ok := pkt.(*packet.PrivateKey) 277 if !ok { 278 return nil, fmt.Errorf("expected private key, got instead: %T", pkt) 279 } 280 if _, ok := privk.PrivateKey.(*rsa.PrivateKey); !ok { 281 return nil, fmt.Errorf("expected RSA private key, got instead: %T", privk.PrivateKey) 282 } 283 return openpgpPrivateKey{privk}, nil 284 } 285 286 // RSAPrivateKey returns a PrivateKey for database use out of a rsa.PrivateKey. 287 func RSAPrivateKey(privk *rsa.PrivateKey) PrivateKey { 288 intPrivk := packet.NewRSAPrivateKey(v1FixedTimestamp, privk) 289 return openpgpPrivateKey{intPrivk} 290 } 291 292 // GenerateKey generates a private/public key pair. 293 func GenerateKey() (PrivateKey, error) { 294 priv, err := rsa.GenerateKey(rand.Reader, 4096) 295 if err != nil { 296 return nil, err 297 } 298 return RSAPrivateKey(priv), nil 299 } 300 301 func encodePrivateKey(privKey PrivateKey) ([]byte, error) { 302 return encodeKey(privKey, "private key") 303 } 304 305 // externally held key pairs 306 307 type extPGPPrivateKey struct { 308 pubKey PublicKey 309 from string 310 externalID string 311 bitLen int 312 doSign func(content []byte) (*packet.Signature, error) 313 } 314 315 func newExtPGPPrivateKey(exportedPubKeyStream io.Reader, from string, sign func(content []byte) (*packet.Signature, error)) (*extPGPPrivateKey, error) { 316 var pubKey *packet.PublicKey 317 318 rd := packet.NewReader(exportedPubKeyStream) 319 for { 320 pkt, err := rd.Next() 321 if err == io.EOF { 322 break 323 } 324 if err != nil { 325 return nil, fmt.Errorf("cannot read exported public key: %v", err) 326 } 327 cand, ok := pkt.(*packet.PublicKey) 328 if ok { 329 if cand.IsSubkey { 330 continue 331 } 332 if pubKey != nil { 333 return nil, fmt.Errorf("cannot select exported public key, found many") 334 } 335 pubKey = cand 336 } 337 } 338 339 if pubKey == nil { 340 return nil, fmt.Errorf("cannot read exported public key, found none (broken export)") 341 342 } 343 344 rsaPubKey, ok := pubKey.PublicKey.(*rsa.PublicKey) 345 if !ok { 346 return nil, fmt.Errorf("not a RSA key") 347 } 348 349 return &extPGPPrivateKey{ 350 pubKey: RSAPublicKey(rsaPubKey), 351 from: from, 352 externalID: fmt.Sprintf("%X", pubKey.Fingerprint), 353 bitLen: rsaPubKey.N.BitLen(), 354 doSign: sign, 355 }, nil 356 } 357 358 func (expk *extPGPPrivateKey) PublicKey() PublicKey { 359 return expk.pubKey 360 } 361 362 func (expk *extPGPPrivateKey) keyEncode(w io.Writer) error { 363 return fmt.Errorf("cannot access external private key to encode it") 364 } 365 366 func (expk *extPGPPrivateKey) sign(content []byte) (*packet.Signature, error) { 367 if expk.bitLen < 4096 { 368 return nil, fmt.Errorf("signing needs at least a 4096 bits key, got %d", expk.bitLen) 369 } 370 371 sig, err := expk.doSign(content) 372 if err != nil { 373 return nil, err 374 } 375 376 badSig := fmt.Sprintf("bad %s produced signature: ", expk.from) 377 378 if sig.Hash != crypto.SHA512 { 379 return nil, fmt.Errorf(badSig + "expected SHA512 digest") 380 } 381 382 err = expk.pubKey.verify(content, sig) 383 if err != nil { 384 return nil, fmt.Errorf(badSig+"it does not verify: %v", err) 385 } 386 387 return sig, nil 388 }