fs.go 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. package fs
  2. import (
  3. "notabug.org/apiote/next-eeze/crypto"
  4. "notabug.org/apiote/next-eeze/password"
  5. "io/ioutil"
  6. "log"
  7. "os"
  8. "os/user"
  9. "path/filepath"
  10. "git.sr.ht/~sircmpwn/go-bare"
  11. )
  12. type EncryptedContent struct {
  13. Salt []byte
  14. CipherText []byte
  15. }
  16. type Credentials struct {
  17. Server string
  18. Username string
  19. Password string
  20. }
  21. type FidoCredential struct {
  22. Cdh []byte
  23. Salt []byte
  24. CredID []byte
  25. }
  26. func getDataLocation() string {
  27. usr, _ := user.Current()
  28. dir := usr.HomeDir
  29. path := filepath.Join(dir, "/.local/share/next-eeze/")
  30. return path
  31. }
  32. // todo memguard passwords, masterPassword
  33. func SaveBare(passwords []password.BarePassword, masterPassword string) error {
  34. salt := crypto.MakeSalt()
  35. // todo memguard
  36. key := crypto.DeriveKey(masterPassword, salt)
  37. result, err := os.Create(getDataLocation() + "/passwords.bare")
  38. if err != nil {
  39. log.Fatal("Error creating passwords file. ", err)
  40. return err
  41. }
  42. defer result.Close()
  43. // todo memguard
  44. bytes, err := bare.Marshal(&passwords)
  45. if err != nil {
  46. log.Fatal("Error marshalling passwords. ", err)
  47. return err
  48. }
  49. cipherText, err := crypto.Encrypt(bytes, key)
  50. if err != nil {
  51. log.Fatal("Error encrypting credentials. ", err)
  52. return err
  53. }
  54. enc := EncryptedContent{
  55. Salt: salt,
  56. CipherText: cipherText,
  57. }
  58. bytes, err = bare.Marshal(&enc)
  59. if err != nil {
  60. log.Fatal("Error marshalling encrypted credentials. ", err)
  61. return err
  62. }
  63. _, err = result.Write(bytes)
  64. if err != nil {
  65. log.Fatal("Error writing to file. ", err)
  66. return err
  67. }
  68. _, err = result.Write(bytes)
  69. if err != nil {
  70. log.Fatal("Error writing to file. ", err)
  71. return err
  72. }
  73. return nil
  74. }
  75. // todo memguard passwords, masterPassword
  76. func Save(passwords []password.NextPassword, masterPassword string) error {
  77. // todo memguard
  78. barePasswords := []password.BarePassword{}
  79. // todo memguard
  80. for _, p := range passwords {
  81. barePasswords = append(barePasswords, p.ToBarePassword())
  82. }
  83. err := SaveBare(barePasswords, masterPassword)
  84. return err
  85. }
  86. // todo memguard masterPassword
  87. func Read(masterPassword string) ([]password.BarePassword, error) {
  88. // todo memguard
  89. passwords := []password.BarePassword{}
  90. f, err := os.Open(getDataLocation() + "/passwords.bare")
  91. if err != nil {
  92. log.Fatal("Error opening. ", err)
  93. return passwords, err
  94. }
  95. defer f.Close()
  96. r := bare.NewReader(f)
  97. salt, err := r.ReadData()
  98. if err != nil {
  99. log.Fatal("Error reading salt. ", err)
  100. return passwords, err
  101. }
  102. cipher, err := r.ReadData()
  103. if err != nil {
  104. log.Fatal("Error reading cipher. ", err)
  105. return passwords, err
  106. }
  107. // todo memguard
  108. key := crypto.DeriveKey(masterPassword, salt)
  109. // todo memguard
  110. plaintext, err := crypto.Decrypt(cipher, key)
  111. if err != nil {
  112. log.Fatal("Error decrypting passwords. ", err)
  113. return passwords, err
  114. }
  115. err = bare.Unmarshal(plaintext, &passwords)
  116. if err != nil {
  117. log.Fatal("Error unmarshalling. ", err)
  118. return nil, err
  119. }
  120. return passwords, nil
  121. }
  122. // todo memguard credentials, masterPassword
  123. func SaveCredentials(credentials Credentials, masterPassword string) error {
  124. salt := crypto.MakeSalt()
  125. // todo memguard
  126. key := crypto.DeriveKey(masterPassword, salt)
  127. result, err := os.Create(getDataLocation() + "/credentials.bare")
  128. if err != nil {
  129. log.Fatal("Error creating credentials file. ", err)
  130. return err
  131. }
  132. defer result.Close()
  133. // todo memguard
  134. bytes, err := bare.Marshal(&credentials)
  135. if err != nil {
  136. log.Fatal("Error marshalling credentials. ", err)
  137. return err
  138. }
  139. cipherText, err := crypto.Encrypt(bytes, key)
  140. if err != nil {
  141. log.Fatal("Error encrypting credentials. ", err)
  142. return err
  143. }
  144. enc := EncryptedContent{
  145. Salt: salt,
  146. CipherText: cipherText,
  147. }
  148. bytes, err = bare.Marshal(&enc)
  149. if err != nil {
  150. log.Fatal("Error marshalling encrypted credentials. ", err)
  151. return err
  152. }
  153. _, err = result.Write(bytes)
  154. if err != nil {
  155. log.Fatal("Error writing to file. ", err)
  156. return err
  157. }
  158. return nil
  159. }
  160. // todo memguard masterPassword
  161. func ReadCredentials(masterPassword string) (Credentials, error) {
  162. enc := EncryptedContent{}
  163. // todo memguard
  164. credentials := Credentials{}
  165. content, err := ioutil.ReadFile(getDataLocation() + "/credentials.bare")
  166. if err != nil {
  167. log.Fatal("Error reading to file. ", err)
  168. return credentials, err
  169. }
  170. err = bare.Unmarshal(content, &enc)
  171. if err != nil {
  172. log.Fatal("Error unmarshalling encrypted. ", err)
  173. return credentials, err
  174. }
  175. // todo memguard
  176. key := crypto.DeriveKey(masterPassword, enc.Salt)
  177. // todo memguard
  178. plaintext, err := crypto.Decrypt(enc.CipherText, key)
  179. if err != nil {
  180. log.Fatal("Error decrypting credentials. ", err)
  181. return credentials, err
  182. }
  183. err = bare.Unmarshal(plaintext, &credentials)
  184. return credentials, nil
  185. }
  186. // todo memguards
  187. func SaveFidoCredential(c FidoCredential) error {
  188. bytes, err := bare.Marshal(&c)
  189. if err != nil {
  190. log.Fatal("Error creating credentials file. ", err)
  191. return err
  192. }
  193. result, err := os.Create(getDataLocation() + "/fido.bare")
  194. if err != nil {
  195. log.Fatal("Error creating credentials file. ", err)
  196. return err
  197. }
  198. defer result.Close()
  199. _, err = result.Write(bytes)
  200. if err != nil {
  201. log.Fatal("Error writing to file. ", err)
  202. return err
  203. }
  204. return nil
  205. }
  206. // todo memguards
  207. func ReadFidoCredential() (FidoCredential, error) {
  208. c := FidoCredential{}
  209. content, err := ioutil.ReadFile(getDataLocation() + "/fido.bare")
  210. if err != nil {
  211. log.Fatal("Error reading to file. ", err)
  212. return c, err
  213. }
  214. err = bare.Unmarshal(content, &c)
  215. if err != nil {
  216. log.Fatal("Error unmarshalling encrypted. ", err)
  217. return c, err
  218. }
  219. return c, nil
  220. }
  221. func RemoveFidoCredential() error {
  222. err := os.Remove(getDataLocation() + "/fido.bare")
  223. if err != nil && os.IsNotExist(err) {
  224. return nil
  225. } else {
  226. return err
  227. }
  228. }
  229. func IsFidoCredentialPresent() (bool, error) {
  230. _, err := os.Stat(getDataLocation() + "/fido.bare")
  231. if err != nil {
  232. if os.IsNotExist(err) {
  233. return false, nil
  234. } else {
  235. return false, err
  236. }
  237. }
  238. return true, nil
  239. }