{"id":20597889,"url":"https://github.com/pkasila/gorm-crypto","last_synced_at":"2025-04-15T00:16:29.788Z","repository":{"id":54535685,"uuid":"325340832","full_name":"pkasila/gorm-crypto","owner":"pkasila","description":"Encrypts or signs any value of JSON compatible type","archived":false,"fork":false,"pushed_at":"2023-05-17T17:41:41.000Z","size":50,"stargazers_count":28,"open_issues_count":2,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-15T00:16:13.916Z","etag":null,"topics":["aes","database","encryption","gorm","rsa","signing"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pkasila.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"patreon":"pkasila"}},"created_at":"2020-12-29T16:55:58.000Z","updated_at":"2024-11-05T22:28:29.000Z","dependencies_parsed_at":"2024-06-19T06:10:43.557Z","dependency_job_id":"abec47af-cbe4-4abe-9e11-ad2cee911aa8","html_url":"https://github.com/pkasila/gorm-crypto","commit_stats":null,"previous_names":["pkosilo/gorm-crypto"],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pkasila%2Fgorm-crypto","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pkasila%2Fgorm-crypto/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pkasila%2Fgorm-crypto/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pkasila%2Fgorm-crypto/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pkasila","download_url":"https://codeload.github.com/pkasila/gorm-crypto/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248981268,"owners_count":21193147,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aes","database","encryption","gorm","rsa","signing"],"created_at":"2024-11-16T08:24:17.696Z","updated_at":"2025-04-15T00:16:29.771Z","avatar_url":"https://github.com/pkasila.png","language":"Go","funding_links":["https://patreon.com/pkasila"],"categories":[],"sub_categories":[],"readme":"# gorm-crypto\nEncrypts any value of JSON compatible type\n\n# Installation\nTo install `gorm-crypto` you need to, as usual, run this command:\n```shell\ngo get github.com/pkasila/gorm-crypto\n```\n\n# How to use it?\n## Initialize\nFirst of all you need to initialize the library **before migrating models**. To do so, you need to decide which\nalgorithm you want to use. (By the way, it's possible to select serializer/deserialize, so in the future you will\nbe able to customize your flow even more).\n### RSA\nIf you want to use RSA, then you need to generate or load key pair and initialize library with `algorithm.RSA`\nwith your private and public keys. To do so, you can simply run code **like** this (you can also use different\npublic and private key files) in your app:\n```golang\nvar privateKey *rsa.PrivateKey\nvar publicKey *rsa.PublicKey\n\n// Different behaviour if there is already a PEM with private key or not\nif _, err := os.Stat(\"private_key.pem\"); os.IsNotExist(err) {\n  // There is no PEM\n  \n  // Generate key pair\n  privateKey, publicKey, err = helpers.RSAGenerateKeyPair(4096)\n\n  if err != nil {\n    panic(err)\n  }\n\n  // Store it\n  privateKeyBytes := helpers.RSAPrivateKeyToBytes(privateKey)\n  err := ioutil.WriteFile(\"private_key.pem\", privateKeyBytes, 0644)\n\n  if err != nil {\n    panic(err)\n  }\n} else {\n  // There is a PEM\n  \n  // Read PEM file with private key\n  bytes, err := ioutil.ReadFile(\"private_key.pem\")\n  if err != nil {\n    panic(err)\n  }\n\n  // Bytes to private key\n  privateKey, err = helpers.RSABytesToPrivateKey(bytes)\n  if err != nil {\n    panic(err)\n  }\n  publicKey = \u0026privateKey.PublicKey\n}\n\n// Use privateKey and publicKey to initialize gormcrypto\ngormcrypto.Init(algorithms.NewRSA(privateKey, publicKey), serialization.NewJSON())\n```\n### AES256GCM\nTo use this library with AES256GCM, you need to initialize it with `algorithm.AES256GCM` with your key passed.\nThere is an example how to initialize library with AES256GCM:\n```golang\naes, err := algorithms.NewAES256GCM([]byte(\"passphrasewhichneedstobe32bytes!\"))\n// algorithms.NewAES can fall with an error, so you should handle it\nif err != nil {\n  panic(err)\n}\ngorm.Init(aes, serialization.NewJSON())\n```\n### AES256CBC\nTo use this library with AES256CBC, you need to initialize it with `algorithm.AES256CBC` with your key passed.\nThere is an example how to initialize library with AES256CBC:\n```golang\naes, err := algorithms.NewAES256CBC([]byte(\"passphrasewhichneedstobe32bytes!\"))\n// algorithms.NewAES can fall with an error, so you should handle it\nif err != nil {\n  panic(err)\n}\ngorm.Init(aes, serialization.NewJSON())\n```\n### Fallbacks\nSometimes you may need to change your algorithm or rotate the keys, the library lets you do so.\nYou just need to initialize the library with `InitWithFallbacks`:\n```golang\n// The fallback algorithm\nrsa := algorithms.NewRSA(privateKey, publicKey)\n\n// The main algorithm\naes, err := algorithms.NewAES([]byte(\"passphrasewhichneedstobe32bytes!\"))\nif err != nil {\n  panic(err)\n}\ngormcrypto.InitWithFallbacks([]algorithms.Algorithm{aes, rsa}, []serialization.Serializer{serialization.NewJSON()})\n```\nThe first algorithm/serializer in the array is the main algorithm, others are the fallback algorithms.\n\n## Use it in a model\nThere is an example of a model with `EncryptedValue`:\n```golang\ntype Application struct {\n  gorm.Model\n  Name               string                      `json:\"name\"`\n  Phone              string                      `json:\"phone\"`\n  Email              string                      `json:\"email\"`\n  Address            gormcrypto.EncryptedValue  `json:\"address\"`\n}\n```\n\n## Create a record with it\nThere is an example of `DB.Create` with a model with `EncryptedValue`:\n```golang\napplication := Application {\n  Name: \"Anonymous\",\n  Phone: \"+375290000000\",\n  Email: \"example@example.com\",\n  Address: gormcrypto.EncryptedValue{Raw: \"Oktyabr'skaya Ploshchad' 1, Minsk 220030\"},\n}\n\nif err = models.DB.Create(\u0026model).Error; err != nil {\n  panic(err)\n}\n```\n\n## Read a record with it\nThere is an example of finding a value using `DB.Find` and using `EncryptedValue.Raw` to access the decrypted value:\n```golang\nvar application Application\n\nif err := db.Find(\u0026application, 1).Error; err != nil {\n  panic(err)\n}\n\nfmt.Printf(\"Decrypted (raw) address: %s\", application.Address.Raw.(string))\n```\n\n## Signing capabilties\nTo initialize library for signing with `SignedValue` you should call `InitSigning` function like this:\n```golang\ngormcrypto.InitSigning([]signing.SignatureAlgorithm{signing.NewECDSA(privateKey, publicKey)}, []serialization.Serializer{serialization.NewJSON()})\n```\nThen you can use `SignedValue` in you structs.\n### Signing algorithms\n#### ECDSA\nExample:\n```golang\n// Generate key pair\nprivateKey, publicKey, _ := helpers.ECDSAGenerateKeyPair()\nalgo := NewECDSA(privateKey, publicKey)\n```\n#### Ed25519\nExample:\n```golang\n// Generate key pair\nprivateKey, publicKey, _ := helpers.Ed25519GenerateKeyPair()\nalgo := NewEd25519(\u0026privateKey, \u0026publicKey)\n```\n### `SignedValue`\n#### How to sign?\nThere is an example of usage of `SignedValue`:\n```golang\napplication := Application {\n  Name: \"Anonymous\",\n  Phone: \"+375290000000\",\n  Email: \"example@example.com\",\n  Address: gormcrypto.SignedValue{Raw: \"Oktyabr'skaya Ploshchad' 1, Minsk 220030\"},\n}\n\nif err = models.DB.Create(\u0026model).Error; err != nil {\n  panic(err)\n}\n```\n#### How to access data and verify integrity?\nYou can access data by using `Raw` field:\n```golang\nvar application Application\n\nif err := db.Find(\u0026application, 1).Error; err != nil {\n  panic(err)\n}\n\nfmt.Printf(\"Raw address: %s\", application.Address.Raw.(string))\n```\nAnd you can verify integrity by accessing `Valid` field:\n```golang\nvalid := application.Address.Valid // true if is valid, false if is not\n```\n**Remember**: if you change `Raw` field, then the `Valid` field won't be\naffected, so after changing `Raw` field you cannot trust `Valid` field.\n\n#### Intented use case\n`SignedValue` is not intended to be used for multiple reads and writes.\nIt is intended to be used to save information to the database with signature\nand then read it after sometime.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpkasila%2Fgorm-crypto","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpkasila%2Fgorm-crypto","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpkasila%2Fgorm-crypto/lists"}