github.com/coreos/mantle@v0.13.0/update/signature/signature.go (about) 1 // Copyright 2016 CoreOS, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package signature 16 17 import ( 18 "crypto" 19 "crypto/rand" 20 "crypto/rsa" 21 _ "crypto/sha256" 22 "crypto/x509" 23 "encoding/pem" 24 "fmt" 25 "hash" 26 27 "github.com/coreos/pkg/capnslog" 28 "github.com/golang/protobuf/proto" 29 30 "github.com/coreos/mantle/update/metadata" 31 ) 32 33 const ( 34 signatureVersion = 2 35 signatureHash = crypto.SHA256 36 developerPubKey = ` 37 -----BEGIN PUBLIC KEY----- 38 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzFS5uVJ+pgibcFLD3kbY 39 k02Edj0HXq31ZT/Bva1sLp3Ysv+QTv/ezjf0gGFfASdgpz6G+zTipS9AIrQr0yFR 40 +tdp1ZsHLGxVwvUoXFftdapqlyj8uQcWjjbN7qJsZu0Ett/qo93hQ5nHW7Sv5dRm 41 /ZsDFqk2Uvyaoef4bF9r03wYpZq7K3oALZ2smETv+A5600mj1Xg5M52QFU67UHls 42 EFkZphrGjiqiCdp9AAbAvE7a5rFcJf86YR73QX08K8BX7OMzkn3DsqdnWvLB3l3W 43 6kvIuP+75SrMNeYAcU8PI1+bzLcAG3VN3jA78zeKALgynUNH50mxuiiU3DO4DZ+p 44 5QIDAQAB 45 -----END PUBLIC KEY-----` 46 developerSecKey = ` 47 -----BEGIN RSA PRIVATE KEY----- 48 MIIEowIBAAKCAQEAzFS5uVJ+pgibcFLD3kbYk02Edj0HXq31ZT/Bva1sLp3Ysv+Q 49 Tv/ezjf0gGFfASdgpz6G+zTipS9AIrQr0yFR+tdp1ZsHLGxVwvUoXFftdapqlyj8 50 uQcWjjbN7qJsZu0Ett/qo93hQ5nHW7Sv5dRm/ZsDFqk2Uvyaoef4bF9r03wYpZq7 51 K3oALZ2smETv+A5600mj1Xg5M52QFU67UHlsEFkZphrGjiqiCdp9AAbAvE7a5rFc 52 Jf86YR73QX08K8BX7OMzkn3DsqdnWvLB3l3W6kvIuP+75SrMNeYAcU8PI1+bzLcA 53 G3VN3jA78zeKALgynUNH50mxuiiU3DO4DZ+p5QIDAQABAoIBAH7ENbE+9+nkPyMx 54 hekaBPVmSz7b3/2iaTNWmckmlY5aSX3LxejtH3rLBjq7rihWGMXJqg6hodcfeGfP 55 Zb0H2AeKq1Nlac7qq05XsKGRv3WXs6dyO1BDkH/Minh5dk1o0NrwEm91kXLSLfe8 56 IsCwxPCjwgfGFTjpFLpL4zjA/nFmWRyk2eyvs5VYRGKbbC83alUy7LutyRdZfw1b 57 nwXldw2m8k/HPbGhaAqPpXTOjckIXZS5Dcp3smrOzwObZ6c3gQzg8upaRmxJVOmk 58 cgCFTe0yUB2GMTEE3SUmuWJyZqECoyQtuiu0yT3igH8MZQpjg9NXm0eho/bXjN36 59 frH+ikUCgYEA7VdCRcisnYWct29j+Bnaio9yXwwxhfoee53a4LQgjw5RLGUe1mXe 60 j56oZ1Mak3Hh55sVQLNXZBuXHQqPsr7KkWXJXedDNFfq1u6by4LeJV0YYiDjjaCM 61 T5G4Tcs7xhBWszLMCjhpJCrwHdGk3aa65UQ+angZlxhyziULCjpb5rMCgYEA3GUb 62 VkqlVuNkHoogOMwg+h1jUSkwtWvP/z/FOXrKjivuwSgQ+i6PsildI3FL/WQtJxgd 63 arB+l0L8TZJ6spFdNXwGmdCLqEcgEBYl11EojOXYLa7oLONI41iRQ3/nBBIqC38P 64 Cs6CZQG/ZpKSoOzXE34BwcrOL99MA2oaVpGHuQcCgYA1IIk3Mbph8FyqOwb3rGHd 65 Dksdt48GXHyiUy2BixCWtS+6blA+0cLGB0/PAS07wAw/WdmiCAMR55Ml7w1Hh6m0 66 bkJrAK9schmhTvwUzBCJ8JLatF37f+qojQfichHJPjMKHd7KkuIGNI5XPmxXKVFA 67 rMwD7SpdRh28w1H7UiDsPQKBgGebnFtXohyTr2hv9K/evo32LM9ltsFC2rga6YOZ 68 BwoI+yeQx1JleyX9LgzQYTHQ2y0quAGE0S4YznVFLCswDQpssMm0cUL9lMQbNVTg 69 kViTYKoxNHKNsqE17Kw3v4l5ZIydAZxJ8qC7TphQxV+jl4RRU1AgIAf/SEO+qH0T 70 0yMXAoGBAN+y9QpGnGX6cgwLQQ7IC6MC+3NRed21s+KxHzpyF+Zh/q6NTLUSgp8H 71 dBmeF4wAZTY+g/fdB9drYeaSdRs3SZsM7gMEvjspjYgE2rV/5gkncFyGKRAiNOR4 72 bsy1Gm/UYLTc8+S3fq/xjg9RCjW9JMwavAwL6oVNNt7nyAXPfvSu 73 -----END RSA PRIVATE KEY----- 74 ` 75 ) 76 77 var ( 78 plog = capnslog.NewPackageLogger("github.com/coreos/mantle", "update/signature") 79 ) 80 81 func NewSignatureHash() hash.Hash { 82 return signatureHash.New() 83 } 84 85 func keySize() (int, error) { 86 pemBlock, _ := pem.Decode([]byte(developerPubKey)) 87 if pemBlock == nil { 88 return 0, fmt.Errorf("unable to parse key") 89 } 90 91 somePub, err := x509.ParsePKIXPublicKey(pemBlock.Bytes) 92 if err != nil { 93 return 0, err 94 } 95 96 rsaPub, ok := somePub.(*rsa.PublicKey) 97 if !ok { 98 return 0, fmt.Errorf("unexpected key type %T", somePub) 99 } 100 101 // This is how the rsa package computes key length. 102 return (rsaPub.N.BitLen() + 7) / 8, nil 103 } 104 105 func SignaturesSize() (int, error) { 106 dataLen, err := keySize() 107 if err != nil { 108 return 0, err 109 } 110 data := make([]byte, dataLen) 111 sigs := &metadata.Signatures{ 112 Signatures: []*metadata.Signatures_Signature{ 113 &metadata.Signatures_Signature{ 114 Version: proto.Uint32(signatureVersion), 115 Data: data, 116 }, 117 }, 118 } 119 return proto.Size(sigs), nil 120 } 121 122 func Sign(sum []byte) (*metadata.Signatures, error) { 123 pemBlock, _ := pem.Decode([]byte(developerSecKey)) 124 if pemBlock == nil { 125 return nil, fmt.Errorf("unable to parse key") 126 } 127 128 rsaKey, err := x509.ParsePKCS1PrivateKey(pemBlock.Bytes) 129 if err != nil { 130 return nil, err 131 } 132 133 sig, err := rsa.SignPKCS1v15(rand.Reader, rsaKey, signatureHash, sum) 134 if err != nil { 135 return nil, err 136 } 137 138 return &metadata.Signatures{ 139 Signatures: []*metadata.Signatures_Signature{ 140 &metadata.Signatures_Signature{ 141 Version: proto.Uint32(signatureVersion), 142 Data: sig, 143 }, 144 }, 145 }, nil 146 } 147 148 func VerifySignature(sum []byte, sigs *metadata.Signatures) error { 149 pemBlock, _ := pem.Decode([]byte(developerPubKey)) 150 if pemBlock == nil { 151 return fmt.Errorf("unable to parse key") 152 } 153 154 somePub, err := x509.ParsePKIXPublicKey(pemBlock.Bytes) 155 if err != nil { 156 return err 157 } 158 159 rsaPub, ok := somePub.(*rsa.PublicKey) 160 if !ok { 161 return fmt.Errorf("unexpected key type %T", somePub) 162 } 163 164 for _, sig := range sigs.Signatures { 165 v := sig.GetVersion() 166 if v != signatureVersion { 167 plog.Debugf("Skipping v%d signature", v) 168 continue 169 } 170 171 if err := rsa.VerifyPKCS1v15(rsaPub, signatureHash, sum, sig.Data); err != nil { 172 plog.Debugf("Cannot verify v%d signature with dev key", v) 173 } else { 174 plog.Infof("Good v%d signature by dev key", v) 175 return nil 176 } 177 178 } 179 180 return fmt.Errorf("no valid signatures found") 181 }