safedata

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 23, 2024 License: BSD-3-Clause, MIT Imports: 1 Imported by: 0

README

safedata

Go Reference

Store credentials (and arbitrary data) securely and persistent. This is useful to store tokens and other types of access credentials.


Usage

This package can be used as standalone (with/without Gio) and also as plugin for Gio.

Using as Standalone:

config := Config{
App: "MyApp"
// ...
}

sh := safedata.NewSafeData(config)

secret := safedata.Secret{
Identifier:  "AccessToken",
Description: "AccessToken for MyApp",
Data:        []byte{0xDE, 0xAD, 0xBE, 0xEF},
}

// Inserting/updating data:
if err := sh.Set(secret); err != nil {
// ...
}

// Retrieve data:
myToken, err := sh.Get("AccessToken")
if err != nil {
// ...
}

Note: safedata.Config varies for each OS, and you should create yourfile_{os}.go for each supported OS. If you are using Gio, it's also possible to create one safedata.Config using giosafedata.NewConfigFromViewEvent.

Using as Gio-Plugin:

Operations:

Operations must be added with .Add(gtx.Ops) method. The operation will be executed at the end of the frame.

  • giosafedata.WriteSecretOp:
    • Writes a Secret.
  • giosafedata.ReadSecretOp:
    • Reads a Secret using the provided Identifier, the response is sent to the given Tag.
  • giosafedata.DeleteSecretOp:
    • Deletes a Secret using the provided Identifier.
  • giosafedata.ListSecretOp:
    • List all Secret which belongs to the current app.

Events:

Events are response sent using the Tag and should be handled with gtx.Events().

  • giosafedata.ErrorEvent:
    • Sent to Tag when it's not possible to write/read/list/delete.
  • giosafedata.SecretsEvent:
    • Sent to Tag as response from ReadSecretOp or ListSecretOp.

Features

OS Windows Android MacOS iOS WebAssembly
Write
Read
List
Delete
API WinCred Android Keystore Keychain Services Keychain Services LocalStorage
  • ❌ = Not supported.
  • ✔ = Supported.

Security/Notes

This package uses what is available on the OS to safely store credentials and any sensible data. However, not all OSes provides such function or have heavily limitations. That is the list of known issues/vulnerability:

  • [Darwin] You must sign your app.

  • [Darwin] Credentials are visible cross-application after user authorization.

  • [Android] Credentials may lose after app uninstall or update.

  • [Windows] Large data is split into multiple credentials, due to maximum size for each credential.

  • [Windows] Credential Storage have a very low capacity, preventing from storing large data or too many credentials.

  • [Windows] Credentials are visible cross-application, without restrictions.

  • [WebAssembly] Credentials are visible to any script in the page, which is vulnerable to XSS.

  • [WebAssembly] Credentials may lose after cache clear (Clear-Site-Data header or invoked by the end-user).

  • This package doesn't check the integrity of the data (you should add your own checksum).

  • Credentials can be modified or deleted externally (usually on device settings and similar).

Background

Since it's a security-related package, I'm listing how it works behind the scenes.

  • [Android] It creates files on the folder specified by Config, that file is encrypted using Android KeyStore. The IV/Nonce is stored into the file. It uses AES-CBC as encryption, since we don't guarantee integrity on any OS.
  • [Darwin] It stores the data into Keychain, directly.
  • [Windows] It creates new credentials using WinCred, as Generic Credentials. Each credential supports upto 512*5 bytes. If the data exceeds the maximum size, new credentials are created using Blake2 derivation for names, starting from index 0, if the data is larger.
  • [WebAssembly] It stores the data into LocalStorage, directly.

Requirements

  • Windows:
    • End-Users: must have Windows 7+.
    • Developers: must have Golang 1.18+ installed (no CGO required).
  • WebAssembly:
    • End-Users: must have WebAssembly enabled browser (usually Safari 13+, Chrome 70+).
    • Developers: must have Golang 1.18+ installed (no CGO required).
  • macOS:
    • End-Users: must have macOS 10+.
    • Developers: must have macOS device with Golang, Xcode, and CLang installed.
  • iOS:
    • End-Users: must have iOS 10+.
    • Developers: must have macOS device with Golang, Xcode, and CLang installed.
  • Android:
    • End-Users: must have Android 6+.
    • Developers: must have Golang 1.18+, OpenJDK 1.8, Android NDK, Android SDK 31 installed (here for more information).

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrNotFound is returned when there's no credentials
	// for the given key.
	ErrNotFound = errors.New("not found")

	// ErrUserRefused is returned when the user refuse to
	// save or retrieve credentials.
	ErrUserRefused = errors.New("user refused")

	// ErrUnsupported is returned when the current OS doesn't
	// supports the current requested feature.
	ErrUnsupported = errors.New("os not supported")

	// ErrMetadataMaxLength is returned when the given identifier
	// hits or exceeds the maximum allowed length.
	ErrMetadataMaxLength = errors.New("metadata exceeds the maximum length")

	// ErrMalformedMetadata is returned when the given identifier
	// contains invalid character. Usually that happens when identifier
	// contains control characters (null, tabs...).
	ErrMalformedMetadata = errors.New("metadata contains invalid characters")
)
View Source
var (
	// DefaultAppName is the unique name to identify the app,
	// you should change it, or provide one name using Config.
	//
	// The DefaultAppName is used when Config.App is empty.
	DefaultAppName = "safedata"
)

Functions

This section is empty.

Types

type Config

type Config struct{}

Config is the configuration for a WebView.

Each OS contains their own settings and options, check each config_* file for more details.

type Looper

type Looper func(identifier string) (next bool)

type SafeData

type SafeData struct {
	// contains filtered or unexported fields
}

func NewSafeData

func NewSafeData(config Config) *SafeData

func (*SafeData) Configure

func (s *SafeData) Configure(config Config)

func (*SafeData) Get

func (s *SafeData) Get(identifier string) (Secret, error)

Get gets the data from credentials manager.

The identifier must match against the identifier previously used for Set.

func (*SafeData) List

func (s *SafeData) List(looper Looper) error

List gets a list of credentials that belongs to the current app.

On WebAssembly that will always return a maximum of one credential, if any.

func (*SafeData) Remove

func (s *SafeData) Remove(identifier string) error

Remove deletes the data and identifier from OS credentials manager.

The identifier is used for searching.

func (*SafeData) Set

func (s *SafeData) Set(secret Secret) error

Set uploads (or updates) the given secret to the OS credentials manager.

The identifier is used for searching, and must be unique, otherwise will replace the previous value.

func (*SafeData) View

func (s *SafeData) View(identifier string, out *Secret) error

View gets the data from credentials manager, and sets the content into the provided out. It may re-use the same Data slice.

The "out" argument MUST NOT be nil. If you want to allocate new Secret for each call, see Get function.

The identifier must match against the identifier previously used for Set.

type Secret

type Secret struct {
	// Identifier is a unique identifier of the secret,
	// it is used to search the secret.
	//
	// The identifier is plain-text and usually is
	// the username or email of the user, or other
	// public identifiable content.
	//
	// That field is not encrypted.
	Identifier string

	// Description is a brief description explaining
	// this data. It may be displayed to the end-user,
	// describing the purpose of that credential. It
	// might be a good practices to include the name
	// of your software into the description.
	//
	// That field is ignored on Android and WASM.
	// That field is not encrypted.
	Description string

	// Data is the arbitrary secret data, it can be one
	// password, token or certificate.
	//
	// That field is encrypted on Android, iOS,
	// macOS and Windows.
	Data []byte
}

Secret represents a data to be stored, and its searchable using Identifier.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL