Xipher is a curated collection of cryptographic primitives put together to perform key/password based asymmetric encryption.
- Allows sharing of data securely between two parties over an insecure channel using asymmetric encryption.
- The sender encrypts the data using a public key (of the receiver - usually derived from a password) and shares the encrypted data with the receiver.
- The receiver decrypts the data using the secret key (or password).
- Encrypts data with the public key generated based on a password.
- Supports stream cipher along with stream compression, resulting in lower memory footprint and smaller ciphertext.
- Supports post-quantum cryptography using the Kyber1024 algorithm.
Download the latest binary from the releases page and add it to your path.
Xipher can be installed with brew using the following command on macOS
brew install shibme/tap/xipher
With Shell (MacOs/Linux):
curl -fsSL https://dev.shib.me/xipher/install/install.sh | sh
With PowerShell (Windows):
irm https://dev.shib.me/xipher/install/install.ps1 | iex
With Shell (MacOs/Linux):
curl -fsSL https://dev.shib.me/xipher/install/install.sh | sh -s v1.1.0
With PowerShell (Windows):
$v="1.1.0"; irm https://dev.shib.me/xipher/install/install.ps1 | iex
You can also run Xipher without installing using Docker:
docker run --rm -v $PWD:/data -it shibme/xipher help
A web interface interoperable with the CLI, implemented using web assembly is available here.
- Receiver opens the Xipher web app on a browser.
- Xipher generates a key pair and stores them in the browser local storage.
- The Xiher web app returns the public key as a URL that can be shared.
- Receiver shares the encryption URL (this contains the public key as a parameter) with the sender.
- Sender opens the public encryption URL (opens Xipher encryption web page).
- Sender inputs the data that needs to be encrypted.
- Xipher encrypts the data using the public key from the URL.
- Xipher returns ciphertext encrypted with the public key.
- Sender sends the encrypted ciphertext to the receiver.
- Receiver inputs the ciphertext in the decryption page.
- Xipher decrypts the ciphertext using the secret key from local storage.
- Xipher returns decrypted data.
The following sequence diagram illustrates the workflow of the web app.
sequenceDiagram
participant RX as Xipher<br>(on Browser)
actor Receiver
actor Sender
participant SX as Xipher<br>(on Browser)
Receiver-->>+RX: Opens Xipher App on browser
RX-->>RX: Generates a key pair and stores them in the browser local storage
RX-->>-Receiver: Returns the Public Key<br>(as a URL that can be shared)
Receiver->>+Sender: Shares the encryption URL<br>(this contains the public key as parameter)
Sender-->>+SX: Opens the public encryption URL<br>(opens Xipher encryption web page)
Sender-->>SX: Inputs the data that needs to be encrypted
SX-->>SX: Encrypts the data using the public key from the URL
SX-->>-Sender: Returns ciphertext encrypted with the Public Key
Sender->>-Receiver: Sends the encrypted ciphertext to the Receiver
Receiver-->>+RX: Inputs the ciphertext<br>(in the decyrption page)
RX-->>RX: Decrypts the ciphertext<br>(using the secret key from local storage)
RX-->>-Receiver: Returns decrypted data
Install the package
go get -u dev.shib.me/xipher
Use it in your code
package main
import (
"encoding/base32"
"fmt"
"dev.shib.me/xipher"
)
func main() {
// Creating a new secret key for password
scrtKey, err := xipher.NewSecretKeyForPassword([]byte("Paws0meKittyKuwan!"))
if err != nil {
panic(err)
}
// Deriving public key from secret key
pubKey, err := scrtKey.PublicKey(false)
if err != nil {
panic(err)
}
publicKeyBytes, err := pubKey.Bytes()
if err != nil {
panic(err)
}
fmt.Println("PublicKey:", base32.StdEncoding.WithPadding(base32.NoPadding).EncodeToString(publicKeyBytes))
platinText := []byte("Hello World!")
// Encrypting plain text with public key
cipherText, err := pubKey.Encrypt(platinText, true)
if err != nil {
panic(err)
}
fmt.Println("Encrypted:", base32.StdEncoding.WithPadding(base32.NoPadding).EncodeToString(cipherText))
// Decrypting cipher text with secret key
plainText, err := scrtKey.Decrypt(cipherText)
if err != nil {
panic(err)
}
fmt.Println("Decrypted:", string(plainText))
}
To use xipher as a web assembly (wasm) module in a browser app, follow the example below.
<html>
<head>
<meta charset="utf-8"/>
<script src="https://dev.shib.me/xipher/wasm/wasm_exec.js"></script>
<script>
const go = new Go();
WebAssembly.instantiateStreaming(fetch("https://dev.shib.me/xipher/wasm/xipher.wasm"), go.importObject).then((result) => {
go.run(result.instance);
});
</script>
</head>
<body>
Call wasm methods that begin with xipher. For example: xipherNewSecretKey()
</body>
</html>
Xipher uses the following algorithms and libraries to achieve its functionality:
- Argon2id for password hashing.
- Curve25519 for elliptic curve cryptography.
- CRYSTALS-Kyber using CIRCL library for post-quantum cryptography.
- XChaCha20-Poly1305 for symmetric encryption.
- Zlib for compression.
The following sequence diagram illustrates the workflow of Xipher in encrypting data using a password based public key.
sequenceDiagram
participant RX as Xipher
actor Receiver
actor Sender
participant SX as Xipher
Receiver-->>+RX: Derive public (inputs password)
RX-->>-Receiver: Returns Public Key
Receiver->>Sender: Shares Public Key
Sender-->>+SX: Encrypt data with public key
SX-->>-Sender: Returns ciphertext encrypted with Public Key
Sender->>Receiver: Sends the encrypted ciphertext to the Receiver
Receiver-->>+RX: Decrypt data (inputs ciphertext and password)
RX-->>-Receiver: Returns decrypted data
This tool/library is provided without any warranties, and there is no guarantee of its stability. Due to the experimental nature of some of its components, it is anticipated that modifications to the code, repository, and API will be made in the future. Caution is advised before incorporating this into a production application. Please report any identified security issues promptly. Your cooperation in notifying us of such concerns is highly appreciated.