github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/swarm/api/act.go (about) 1 2 //此源码被清华学神尹成大魔王专业翻译分析并修改 3 //尹成QQ77025077 4 //尹成微信18510341407 5 //尹成所在QQ群721929980 6 //尹成邮箱 yinc13@mails.tsinghua.edu.cn 7 //尹成毕业于清华大学,微软区块链领域全球最有价值专家 8 //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620 9 package api 10 11 import ( 12 "context" 13 "crypto/ecdsa" 14 "crypto/rand" 15 "encoding/hex" 16 "encoding/json" 17 "errors" 18 "fmt" 19 "io" 20 "strings" 21 "time" 22 23 "github.com/ethereum/go-ethereum/common" 24 "github.com/ethereum/go-ethereum/crypto" 25 "github.com/ethereum/go-ethereum/crypto/ecies" 26 "github.com/ethereum/go-ethereum/crypto/sha3" 27 "github.com/ethereum/go-ethereum/swarm/log" 28 "github.com/ethereum/go-ethereum/swarm/sctx" 29 "github.com/ethereum/go-ethereum/swarm/storage" 30 "golang.org/x/crypto/scrypt" 31 cli "gopkg.in/urfave/cli.v1" 32 ) 33 34 var ( 35 ErrDecrypt = errors.New("cant decrypt - forbidden") 36 ErrUnknownAccessType = errors.New("unknown access type (or not implemented)") 37 ErrDecryptDomainForbidden = errors.New("decryption request domain forbidden - can only decrypt on localhost") 38 AllowedDecryptDomains = []string{ 39 "localhost", 40 "127.0.0.1", 41 } 42 ) 43 44 const EMPTY_CREDENTIALS = "" 45 46 type AccessEntry struct { 47 Type AccessType 48 Publisher string 49 Salt []byte 50 Act string 51 KdfParams *KdfParams 52 } 53 54 type DecryptFunc func(*ManifestEntry) error 55 56 func (a *AccessEntry) MarshalJSON() (out []byte, err error) { 57 58 return json.Marshal(struct { 59 Type AccessType `json:"type,omitempty"` 60 Publisher string `json:"publisher,omitempty"` 61 Salt string `json:"salt,omitempty"` 62 Act string `json:"act,omitempty"` 63 KdfParams *KdfParams `json:"kdf_params,omitempty"` 64 }{ 65 Type: a.Type, 66 Publisher: a.Publisher, 67 Salt: hex.EncodeToString(a.Salt), 68 Act: a.Act, 69 KdfParams: a.KdfParams, 70 }) 71 72 } 73 74 func (a *AccessEntry) UnmarshalJSON(value []byte) error { 75 v := struct { 76 Type AccessType `json:"type,omitempty"` 77 Publisher string `json:"publisher,omitempty"` 78 Salt string `json:"salt,omitempty"` 79 Act string `json:"act,omitempty"` 80 KdfParams *KdfParams `json:"kdf_params,omitempty"` 81 }{} 82 83 err := json.Unmarshal(value, &v) 84 if err != nil { 85 return err 86 } 87 a.Act = v.Act 88 a.KdfParams = v.KdfParams 89 a.Publisher = v.Publisher 90 a.Salt, err = hex.DecodeString(v.Salt) 91 if err != nil { 92 return err 93 } 94 if len(a.Salt) != 32 { 95 return errors.New("salt should be 32 bytes long") 96 } 97 a.Type = v.Type 98 return nil 99 } 100 101 type KdfParams struct { 102 N int `json:"n"` 103 P int `json:"p"` 104 R int `json:"r"` 105 } 106 107 type AccessType string 108 109 const AccessTypePass = AccessType("pass") 110 const AccessTypePK = AccessType("pk") 111 const AccessTypeACT = AccessType("act") 112 113 func NewAccessEntryPassword(salt []byte, kdfParams *KdfParams) (*AccessEntry, error) { 114 if len(salt) != 32 { 115 return nil, fmt.Errorf("salt should be 32 bytes long") 116 } 117 return &AccessEntry{ 118 Type: AccessTypePass, 119 Salt: salt, 120 KdfParams: kdfParams, 121 }, nil 122 } 123 124 func NewAccessEntryPK(publisher string, salt []byte) (*AccessEntry, error) { 125 if len(publisher) != 66 { 126 return nil, fmt.Errorf("publisher should be 66 characters long, got %d", len(publisher)) 127 } 128 if len(salt) != 32 { 129 return nil, fmt.Errorf("salt should be 32 bytes long") 130 } 131 return &AccessEntry{ 132 Type: AccessTypePK, 133 Publisher: publisher, 134 Salt: salt, 135 }, nil 136 } 137 138 func NewAccessEntryACT(publisher string, salt []byte, act string) (*AccessEntry, error) { 139 if len(salt) != 32 { 140 return nil, fmt.Errorf("salt should be 32 bytes long") 141 } 142 if len(publisher) != 66 { 143 return nil, fmt.Errorf("publisher should be 66 characters long") 144 } 145 146 return &AccessEntry{ 147 Type: AccessTypeACT, 148 Publisher: publisher, 149 Salt: salt, 150 Act: act, 151 }, nil 152 } 153 154 func NOOPDecrypt(*ManifestEntry) error { 155 return nil 156 } 157 158 var DefaultKdfParams = NewKdfParams(262144, 1, 8) 159 160 func NewKdfParams(n, p, r int) *KdfParams { 161 162 return &KdfParams{ 163 N: n, 164 P: p, 165 R: r, 166 } 167 } 168 169 //newsessionkeypassword基于共享机密(密码)和给定的salt创建会话密钥 170 //和访问项中的kdf参数 171 func NewSessionKeyPassword(password string, accessEntry *AccessEntry) ([]byte, error) { 172 if accessEntry.Type != AccessTypePass { 173 return nil, errors.New("incorrect access entry type") 174 } 175 return scrypt.Key( 176 []byte(password), 177 accessEntry.Salt, 178 accessEntry.KdfParams.N, 179 accessEntry.KdfParams.R, 180 accessEntry.KdfParams.P, 181 32, 182 ) 183 } 184 185 //newsessionkeypk为给定的密钥对和给定的salt值使用ECDH共享机密创建新的act会话密钥 186 func NewSessionKeyPK(private *ecdsa.PrivateKey, public *ecdsa.PublicKey, salt []byte) ([]byte, error) { 187 granteePubEcies := ecies.ImportECDSAPublic(public) 188 privateKey := ecies.ImportECDSA(private) 189 190 bytes, err := privateKey.GenerateShared(granteePubEcies, 16, 16) 191 if err != nil { 192 return nil, err 193 } 194 bytes = append(salt, bytes...) 195 sessionKey := crypto.Keccak256(bytes) 196 return sessionKey, nil 197 } 198 199 func (a *API) NodeSessionKey(privateKey *ecdsa.PrivateKey, publicKey *ecdsa.PublicKey, salt []byte) ([]byte, error) { 200 return NewSessionKeyPK(privateKey, publicKey, salt) 201 } 202 func (a *API) doDecrypt(ctx context.Context, credentials string, pk *ecdsa.PrivateKey) DecryptFunc { 203 return func(m *ManifestEntry) error { 204 if m.Access == nil { 205 return nil 206 } 207 208 allowed := false 209 requestDomain := sctx.GetHost(ctx) 210 for _, v := range AllowedDecryptDomains { 211 if strings.Contains(requestDomain, v) { 212 allowed = true 213 } 214 } 215 216 if !allowed { 217 return ErrDecryptDomainForbidden 218 } 219 220 switch m.Access.Type { 221 case "pass": 222 if credentials != "" { 223 key, err := NewSessionKeyPassword(credentials, m.Access) 224 if err != nil { 225 return err 226 } 227 228 ref, err := hex.DecodeString(m.Hash) 229 if err != nil { 230 return err 231 } 232 233 enc := NewRefEncryption(len(ref) - 8) 234 decodedRef, err := enc.Decrypt(ref, key) 235 if err != nil { 236 return ErrDecrypt 237 } 238 239 m.Hash = hex.EncodeToString(decodedRef) 240 m.Access = nil 241 return nil 242 } 243 return ErrDecrypt 244 case "pk": 245 publisherBytes, err := hex.DecodeString(m.Access.Publisher) 246 if err != nil { 247 return ErrDecrypt 248 } 249 publisher, err := crypto.DecompressPubkey(publisherBytes) 250 if err != nil { 251 return ErrDecrypt 252 } 253 key, err := a.NodeSessionKey(pk, publisher, m.Access.Salt) 254 if err != nil { 255 return ErrDecrypt 256 } 257 ref, err := hex.DecodeString(m.Hash) 258 if err != nil { 259 return err 260 } 261 262 enc := NewRefEncryption(len(ref) - 8) 263 decodedRef, err := enc.Decrypt(ref, key) 264 if err != nil { 265 return ErrDecrypt 266 } 267 268 m.Hash = hex.EncodeToString(decodedRef) 269 m.Access = nil 270 return nil 271 case "act": 272 publisherBytes, err := hex.DecodeString(m.Access.Publisher) 273 if err != nil { 274 return ErrDecrypt 275 } 276 publisher, err := crypto.DecompressPubkey(publisherBytes) 277 if err != nil { 278 return ErrDecrypt 279 } 280 281 sessionKey, err := a.NodeSessionKey(pk, publisher, m.Access.Salt) 282 if err != nil { 283 return ErrDecrypt 284 } 285 286 hasher := sha3.NewKeccak256() 287 hasher.Write(append(sessionKey, 0)) 288 lookupKey := hasher.Sum(nil) 289 290 hasher.Reset() 291 292 hasher.Write(append(sessionKey, 1)) 293 accessKeyDecryptionKey := hasher.Sum(nil) 294 295 lk := hex.EncodeToString(lookupKey) 296 list, err := a.GetManifestList(ctx, NOOPDecrypt, storage.Address(common.Hex2Bytes(m.Access.Act)), lk) 297 298 found := "" 299 for _, v := range list.Entries { 300 if v.Path == lk { 301 found = v.Hash 302 } 303 } 304 305 if found == "" { 306 return ErrDecrypt 307 } 308 309 v, err := hex.DecodeString(found) 310 if err != nil { 311 return err 312 } 313 enc := NewRefEncryption(len(v) - 8) 314 decodedRef, err := enc.Decrypt(v, accessKeyDecryptionKey) 315 if err != nil { 316 return ErrDecrypt 317 } 318 319 ref, err := hex.DecodeString(m.Hash) 320 if err != nil { 321 return err 322 } 323 324 enc = NewRefEncryption(len(ref) - 8) 325 decodedMainRef, err := enc.Decrypt(ref, decodedRef) 326 if err != nil { 327 return ErrDecrypt 328 } 329 m.Hash = hex.EncodeToString(decodedMainRef) 330 m.Access = nil 331 return nil 332 } 333 return ErrUnknownAccessType 334 } 335 } 336 337 func GenerateAccessControlManifest(ctx *cli.Context, ref string, accessKey []byte, ae *AccessEntry) (*Manifest, error) { 338 refBytes, err := hex.DecodeString(ref) 339 if err != nil { 340 return nil, err 341 } 342 //用accesskey加密ref 343 enc := NewRefEncryption(len(refBytes)) 344 encrypted, err := enc.Encrypt(refBytes, accessKey) 345 if err != nil { 346 return nil, err 347 } 348 349 m := &Manifest{ 350 Entries: []ManifestEntry{ 351 { 352 Hash: hex.EncodeToString(encrypted), 353 ContentType: ManifestType, 354 ModTime: time.Now(), 355 Access: ae, 356 }, 357 }, 358 } 359 360 return m, nil 361 } 362 363 func DoPKNew(ctx *cli.Context, privateKey *ecdsa.PrivateKey, granteePublicKey string, salt []byte) (sessionKey []byte, ae *AccessEntry, err error) { 364 if granteePublicKey == "" { 365 return nil, nil, errors.New("need a grantee Public Key") 366 } 367 b, err := hex.DecodeString(granteePublicKey) 368 if err != nil { 369 log.Error("error decoding grantee public key", "err", err) 370 return nil, nil, err 371 } 372 373 granteePub, err := crypto.DecompressPubkey(b) 374 if err != nil { 375 log.Error("error decompressing grantee public key", "err", err) 376 return nil, nil, err 377 } 378 379 sessionKey, err = NewSessionKeyPK(privateKey, granteePub, salt) 380 if err != nil { 381 log.Error("error getting session key", "err", err) 382 return nil, nil, err 383 } 384 385 ae, err = NewAccessEntryPK(hex.EncodeToString(crypto.CompressPubkey(&privateKey.PublicKey)), salt) 386 if err != nil { 387 log.Error("error generating access entry", "err", err) 388 return nil, nil, err 389 } 390 391 return sessionKey, ae, nil 392 } 393 394 func DoACTNew(ctx *cli.Context, privateKey *ecdsa.PrivateKey, salt []byte, grantees []string) (accessKey []byte, ae *AccessEntry, actManifest *Manifest, err error) { 395 if len(grantees) == 0 { 396 return nil, nil, nil, errors.New("did not get any grantee public keys") 397 } 398 399 publisherPub := hex.EncodeToString(crypto.CompressPubkey(&privateKey.PublicKey)) 400 grantees = append(grantees, publisherPub) 401 402 accessKey = make([]byte, 32) 403 if _, err := io.ReadFull(rand.Reader, salt); err != nil { 404 panic("reading from crypto/rand failed: " + err.Error()) 405 } 406 if _, err := io.ReadFull(rand.Reader, accessKey); err != nil { 407 panic("reading from crypto/rand failed: " + err.Error()) 408 } 409 410 lookupPathEncryptedAccessKeyMap := make(map[string]string) 411 i := 0 412 for _, v := range grantees { 413 i++ 414 if v == "" { 415 return nil, nil, nil, errors.New("need a grantee Public Key") 416 } 417 b, err := hex.DecodeString(v) 418 if err != nil { 419 log.Error("error decoding grantee public key", "err", err) 420 return nil, nil, nil, err 421 } 422 423 granteePub, err := crypto.DecompressPubkey(b) 424 if err != nil { 425 log.Error("error decompressing grantee public key", "err", err) 426 return nil, nil, nil, err 427 } 428 sessionKey, err := NewSessionKeyPK(privateKey, granteePub, salt) 429 430 hasher := sha3.NewKeccak256() 431 hasher.Write(append(sessionKey, 0)) 432 lookupKey := hasher.Sum(nil) 433 434 hasher.Reset() 435 hasher.Write(append(sessionKey, 1)) 436 437 accessKeyEncryptionKey := hasher.Sum(nil) 438 439 enc := NewRefEncryption(len(accessKey)) 440 encryptedAccessKey, err := enc.Encrypt(accessKey, accessKeyEncryptionKey) 441 442 lookupPathEncryptedAccessKeyMap[hex.EncodeToString(lookupKey)] = hex.EncodeToString(encryptedAccessKey) 443 } 444 445 m := &Manifest{ 446 Entries: []ManifestEntry{}, 447 } 448 449 for k, v := range lookupPathEncryptedAccessKeyMap { 450 m.Entries = append(m.Entries, ManifestEntry{ 451 Path: k, 452 Hash: v, 453 ContentType: "text/plain", 454 }) 455 } 456 457 ae, err = NewAccessEntryACT(hex.EncodeToString(crypto.CompressPubkey(&privateKey.PublicKey)), salt, "") 458 if err != nil { 459 return nil, nil, nil, err 460 } 461 462 return accessKey, ae, m, nil 463 } 464 465 func DoPasswordNew(ctx *cli.Context, password string, salt []byte) (sessionKey []byte, ae *AccessEntry, err error) { 466 ae, err = NewAccessEntryPassword(salt, DefaultKdfParams) 467 if err != nil { 468 return nil, nil, err 469 } 470 471 sessionKey, err = NewSessionKeyPassword(password, ae) 472 if err != nil { 473 return nil, nil, err 474 } 475 return sessionKey, ae, nil 476 }