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