act.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468
  1. package api
  2. import (
  3. "context"
  4. "crypto/ecdsa"
  5. "crypto/rand"
  6. "encoding/hex"
  7. "encoding/json"
  8. "errors"
  9. "fmt"
  10. "io"
  11. "strings"
  12. "time"
  13. "github.com/ethereum/go-ethereum/common"
  14. "github.com/ethereum/go-ethereum/crypto"
  15. "github.com/ethereum/go-ethereum/crypto/ecies"
  16. "github.com/ethereum/go-ethereum/crypto/sha3"
  17. "github.com/ethereum/go-ethereum/swarm/log"
  18. "github.com/ethereum/go-ethereum/swarm/sctx"
  19. "github.com/ethereum/go-ethereum/swarm/storage"
  20. "golang.org/x/crypto/scrypt"
  21. cli "gopkg.in/urfave/cli.v1"
  22. )
  23. var (
  24. ErrDecrypt = errors.New("cant decrypt - forbidden")
  25. ErrUnknownAccessType = errors.New("unknown access type (or not implemented)")
  26. ErrDecryptDomainForbidden = errors.New("decryption request domain forbidden - can only decrypt on localhost")
  27. AllowedDecryptDomains = []string{
  28. "localhost",
  29. "127.0.0.1",
  30. }
  31. )
  32. const EMPTY_CREDENTIALS = ""
  33. type AccessEntry struct {
  34. Type AccessType
  35. Publisher string
  36. Salt []byte
  37. Act string
  38. KdfParams *KdfParams
  39. }
  40. type DecryptFunc func(*ManifestEntry) error
  41. func (a *AccessEntry) MarshalJSON() (out []byte, err error) {
  42. return json.Marshal(struct {
  43. Type AccessType `json:"type,omitempty"`
  44. Publisher string `json:"publisher,omitempty"`
  45. Salt string `json:"salt,omitempty"`
  46. Act string `json:"act,omitempty"`
  47. KdfParams *KdfParams `json:"kdf_params,omitempty"`
  48. }{
  49. Type: a.Type,
  50. Publisher: a.Publisher,
  51. Salt: hex.EncodeToString(a.Salt),
  52. Act: a.Act,
  53. KdfParams: a.KdfParams,
  54. })
  55. }
  56. func (a *AccessEntry) UnmarshalJSON(value []byte) error {
  57. v := struct {
  58. Type AccessType `json:"type,omitempty"`
  59. Publisher string `json:"publisher,omitempty"`
  60. Salt string `json:"salt,omitempty"`
  61. Act string `json:"act,omitempty"`
  62. KdfParams *KdfParams `json:"kdf_params,omitempty"`
  63. }{}
  64. err := json.Unmarshal(value, &v)
  65. if err != nil {
  66. return err
  67. }
  68. a.Act = v.Act
  69. a.KdfParams = v.KdfParams
  70. a.Publisher = v.Publisher
  71. a.Salt, err = hex.DecodeString(v.Salt)
  72. if err != nil {
  73. return err
  74. }
  75. if len(a.Salt) != 32 {
  76. return errors.New("salt should be 32 bytes long")
  77. }
  78. a.Type = v.Type
  79. return nil
  80. }
  81. type KdfParams struct {
  82. N int `json:"n"`
  83. P int `json:"p"`
  84. R int `json:"r"`
  85. }
  86. type AccessType string
  87. const AccessTypePass = AccessType("pass")
  88. const AccessTypePK = AccessType("pk")
  89. const AccessTypeACT = AccessType("act")
  90. func NewAccessEntryPassword(salt []byte, kdfParams *KdfParams) (*AccessEntry, error) {
  91. if len(salt) != 32 {
  92. return nil, fmt.Errorf("salt should be 32 bytes long")
  93. }
  94. return &AccessEntry{
  95. Type: AccessTypePass,
  96. Salt: salt,
  97. KdfParams: kdfParams,
  98. }, nil
  99. }
  100. func NewAccessEntryPK(publisher string, salt []byte) (*AccessEntry, error) {
  101. if len(publisher) != 66 {
  102. return nil, fmt.Errorf("publisher should be 66 characters long, got %d", len(publisher))
  103. }
  104. if len(salt) != 32 {
  105. return nil, fmt.Errorf("salt should be 32 bytes long")
  106. }
  107. return &AccessEntry{
  108. Type: AccessTypePK,
  109. Publisher: publisher,
  110. Salt: salt,
  111. }, nil
  112. }
  113. func NewAccessEntryACT(publisher string, salt []byte, act string) (*AccessEntry, error) {
  114. if len(salt) != 32 {
  115. return nil, fmt.Errorf("salt should be 32 bytes long")
  116. }
  117. if len(publisher) != 66 {
  118. return nil, fmt.Errorf("publisher should be 66 characters long")
  119. }
  120. return &AccessEntry{
  121. Type: AccessTypeACT,
  122. Publisher: publisher,
  123. Salt: salt,
  124. Act: act,
  125. }, nil
  126. }
  127. func NOOPDecrypt(*ManifestEntry) error {
  128. return nil
  129. }
  130. var DefaultKdfParams = NewKdfParams(262144, 1, 8)
  131. func NewKdfParams(n, p, r int) *KdfParams {
  132. return &KdfParams{
  133. N: n,
  134. P: p,
  135. R: r,
  136. }
  137. }
  138. // NewSessionKeyPassword creates a session key based on a shared secret (password) and the given salt
  139. // and kdf parameters in the access entry
  140. func NewSessionKeyPassword(password string, accessEntry *AccessEntry) ([]byte, error) {
  141. if accessEntry.Type != AccessTypePass {
  142. return nil, errors.New("incorrect access entry type")
  143. }
  144. return scrypt.Key(
  145. []byte(password),
  146. accessEntry.Salt,
  147. accessEntry.KdfParams.N,
  148. accessEntry.KdfParams.R,
  149. accessEntry.KdfParams.P,
  150. 32,
  151. )
  152. }
  153. // NewSessionKeyPK creates a new ACT Session Key using an ECDH shared secret for the given key pair and the given salt value
  154. func NewSessionKeyPK(private *ecdsa.PrivateKey, public *ecdsa.PublicKey, salt []byte) ([]byte, error) {
  155. granteePubEcies := ecies.ImportECDSAPublic(public)
  156. privateKey := ecies.ImportECDSA(private)
  157. bytes, err := privateKey.GenerateShared(granteePubEcies, 16, 16)
  158. if err != nil {
  159. return nil, err
  160. }
  161. bytes = append(salt, bytes...)
  162. sessionKey := crypto.Keccak256(bytes)
  163. return sessionKey, nil
  164. }
  165. func (a *API) NodeSessionKey(privateKey *ecdsa.PrivateKey, publicKey *ecdsa.PublicKey, salt []byte) ([]byte, error) {
  166. return NewSessionKeyPK(privateKey, publicKey, salt)
  167. }
  168. func (a *API) doDecrypt(ctx context.Context, credentials string, pk *ecdsa.PrivateKey) DecryptFunc {
  169. return func(m *ManifestEntry) error {
  170. if m.Access == nil {
  171. return nil
  172. }
  173. allowed := false
  174. requestDomain := sctx.GetHost(ctx)
  175. for _, v := range AllowedDecryptDomains {
  176. if strings.Contains(requestDomain, v) {
  177. allowed = true
  178. }
  179. }
  180. if !allowed {
  181. return ErrDecryptDomainForbidden
  182. }
  183. switch m.Access.Type {
  184. case "pass":
  185. if credentials != "" {
  186. key, err := NewSessionKeyPassword(credentials, m.Access)
  187. if err != nil {
  188. return err
  189. }
  190. ref, err := hex.DecodeString(m.Hash)
  191. if err != nil {
  192. return err
  193. }
  194. enc := NewRefEncryption(len(ref) - 8)
  195. decodedRef, err := enc.Decrypt(ref, key)
  196. if err != nil {
  197. return ErrDecrypt
  198. }
  199. m.Hash = hex.EncodeToString(decodedRef)
  200. m.Access = nil
  201. return nil
  202. }
  203. return ErrDecrypt
  204. case "pk":
  205. publisherBytes, err := hex.DecodeString(m.Access.Publisher)
  206. if err != nil {
  207. return ErrDecrypt
  208. }
  209. publisher, err := crypto.DecompressPubkey(publisherBytes)
  210. if err != nil {
  211. return ErrDecrypt
  212. }
  213. key, err := a.NodeSessionKey(pk, publisher, m.Access.Salt)
  214. if err != nil {
  215. return ErrDecrypt
  216. }
  217. ref, err := hex.DecodeString(m.Hash)
  218. if err != nil {
  219. return err
  220. }
  221. enc := NewRefEncryption(len(ref) - 8)
  222. decodedRef, err := enc.Decrypt(ref, key)
  223. if err != nil {
  224. return ErrDecrypt
  225. }
  226. m.Hash = hex.EncodeToString(decodedRef)
  227. m.Access = nil
  228. return nil
  229. case "act":
  230. publisherBytes, err := hex.DecodeString(m.Access.Publisher)
  231. if err != nil {
  232. return ErrDecrypt
  233. }
  234. publisher, err := crypto.DecompressPubkey(publisherBytes)
  235. if err != nil {
  236. return ErrDecrypt
  237. }
  238. sessionKey, err := a.NodeSessionKey(pk, publisher, m.Access.Salt)
  239. if err != nil {
  240. return ErrDecrypt
  241. }
  242. hasher := sha3.NewKeccak256()
  243. hasher.Write(append(sessionKey, 0))
  244. lookupKey := hasher.Sum(nil)
  245. hasher.Reset()
  246. hasher.Write(append(sessionKey, 1))
  247. accessKeyDecryptionKey := hasher.Sum(nil)
  248. lk := hex.EncodeToString(lookupKey)
  249. list, err := a.GetManifestList(ctx, NOOPDecrypt, storage.Address(common.Hex2Bytes(m.Access.Act)), lk)
  250. found := ""
  251. for _, v := range list.Entries {
  252. if v.Path == lk {
  253. found = v.Hash
  254. }
  255. }
  256. if found == "" {
  257. return ErrDecrypt
  258. }
  259. v, err := hex.DecodeString(found)
  260. if err != nil {
  261. return err
  262. }
  263. enc := NewRefEncryption(len(v) - 8)
  264. decodedRef, err := enc.Decrypt(v, accessKeyDecryptionKey)
  265. if err != nil {
  266. return ErrDecrypt
  267. }
  268. ref, err := hex.DecodeString(m.Hash)
  269. if err != nil {
  270. return err
  271. }
  272. enc = NewRefEncryption(len(ref) - 8)
  273. decodedMainRef, err := enc.Decrypt(ref, decodedRef)
  274. if err != nil {
  275. return ErrDecrypt
  276. }
  277. m.Hash = hex.EncodeToString(decodedMainRef)
  278. m.Access = nil
  279. return nil
  280. }
  281. return ErrUnknownAccessType
  282. }
  283. }
  284. func GenerateAccessControlManifest(ctx *cli.Context, ref string, accessKey []byte, ae *AccessEntry) (*Manifest, error) {
  285. refBytes, err := hex.DecodeString(ref)
  286. if err != nil {
  287. return nil, err
  288. }
  289. // encrypt ref with accessKey
  290. enc := NewRefEncryption(len(refBytes))
  291. encrypted, err := enc.Encrypt(refBytes, accessKey)
  292. if err != nil {
  293. return nil, err
  294. }
  295. m := &Manifest{
  296. Entries: []ManifestEntry{
  297. {
  298. Hash: hex.EncodeToString(encrypted),
  299. ContentType: ManifestType,
  300. ModTime: time.Now(),
  301. Access: ae,
  302. },
  303. },
  304. }
  305. return m, nil
  306. }
  307. func DoPKNew(ctx *cli.Context, privateKey *ecdsa.PrivateKey, granteePublicKey string, salt []byte) (sessionKey []byte, ae *AccessEntry, err error) {
  308. if granteePublicKey == "" {
  309. return nil, nil, errors.New("need a grantee Public Key")
  310. }
  311. b, err := hex.DecodeString(granteePublicKey)
  312. if err != nil {
  313. log.Error("error decoding grantee public key", "err", err)
  314. return nil, nil, err
  315. }
  316. granteePub, err := crypto.DecompressPubkey(b)
  317. if err != nil {
  318. log.Error("error decompressing grantee public key", "err", err)
  319. return nil, nil, err
  320. }
  321. sessionKey, err = NewSessionKeyPK(privateKey, granteePub, salt)
  322. if err != nil {
  323. log.Error("error getting session key", "err", err)
  324. return nil, nil, err
  325. }
  326. ae, err = NewAccessEntryPK(hex.EncodeToString(crypto.CompressPubkey(&privateKey.PublicKey)), salt)
  327. if err != nil {
  328. log.Error("error generating access entry", "err", err)
  329. return nil, nil, err
  330. }
  331. return sessionKey, ae, nil
  332. }
  333. func DoACTNew(ctx *cli.Context, privateKey *ecdsa.PrivateKey, salt []byte, grantees []string) (accessKey []byte, ae *AccessEntry, actManifest *Manifest, err error) {
  334. if len(grantees) == 0 {
  335. return nil, nil, nil, errors.New("did not get any grantee public keys")
  336. }
  337. publisherPub := hex.EncodeToString(crypto.CompressPubkey(&privateKey.PublicKey))
  338. grantees = append(grantees, publisherPub)
  339. accessKey = make([]byte, 32)
  340. if _, err := io.ReadFull(rand.Reader, salt); err != nil {
  341. panic("reading from crypto/rand failed: " + err.Error())
  342. }
  343. if _, err := io.ReadFull(rand.Reader, accessKey); err != nil {
  344. panic("reading from crypto/rand failed: " + err.Error())
  345. }
  346. lookupPathEncryptedAccessKeyMap := make(map[string]string)
  347. i := 0
  348. for _, v := range grantees {
  349. i++
  350. if v == "" {
  351. return nil, nil, nil, errors.New("need a grantee Public Key")
  352. }
  353. b, err := hex.DecodeString(v)
  354. if err != nil {
  355. log.Error("error decoding grantee public key", "err", err)
  356. return nil, nil, nil, err
  357. }
  358. granteePub, err := crypto.DecompressPubkey(b)
  359. if err != nil {
  360. log.Error("error decompressing grantee public key", "err", err)
  361. return nil, nil, nil, err
  362. }
  363. sessionKey, err := NewSessionKeyPK(privateKey, granteePub, salt)
  364. hasher := sha3.NewKeccak256()
  365. hasher.Write(append(sessionKey, 0))
  366. lookupKey := hasher.Sum(nil)
  367. hasher.Reset()
  368. hasher.Write(append(sessionKey, 1))
  369. accessKeyEncryptionKey := hasher.Sum(nil)
  370. enc := NewRefEncryption(len(accessKey))
  371. encryptedAccessKey, err := enc.Encrypt(accessKey, accessKeyEncryptionKey)
  372. lookupPathEncryptedAccessKeyMap[hex.EncodeToString(lookupKey)] = hex.EncodeToString(encryptedAccessKey)
  373. }
  374. m := &Manifest{
  375. Entries: []ManifestEntry{},
  376. }
  377. for k, v := range lookupPathEncryptedAccessKeyMap {
  378. m.Entries = append(m.Entries, ManifestEntry{
  379. Path: k,
  380. Hash: v,
  381. ContentType: "text/plain",
  382. })
  383. }
  384. ae, err = NewAccessEntryACT(hex.EncodeToString(crypto.CompressPubkey(&privateKey.PublicKey)), salt, "")
  385. if err != nil {
  386. return nil, nil, nil, err
  387. }
  388. return accessKey, ae, m, nil
  389. }
  390. func DoPasswordNew(ctx *cli.Context, password string, salt []byte) (sessionKey []byte, ae *AccessEntry, err error) {
  391. ae, err = NewAccessEntryPassword(salt, DefaultKdfParams)
  392. if err != nil {
  393. return nil, nil, err
  394. }
  395. sessionKey, err = NewSessionKeyPassword(password, ae)
  396. if err != nil {
  397. return nil, nil, err
  398. }
  399. return sessionKey, ae, nil
  400. }