passw0rdpublic alpha
passw0rd.io

Virgil Security presents free toolkit that protects user passwords from data breaches and both online and offline attacks

Protection from online and offline attacks
User data encryption with a personal key
No trust, no cost, no downtime
Instant invalidation of stolen database

PHE Authors: Russell W. F. Lai, Christoph Egger, Manuel Reinert, Sherman S. M. Chow, Matteo Maffei and Dominique Schroder

Powered byVirgilSecurity, Inc.

six vital steps to protect user passwords in a database_

  • 1. Download & Run passw0rd CLI

    Begin protecting your passwords by creating a free passw0rd account with the passw0rd CLI utility.

    Download the preferred CLI package with one of the links below. Passw0rd CLI is provided as a binary file, and it is available for:

    Then, Run the passw0rd CLI from its folder with the following command:

    ./passw0rd
    

    More information about the passw0rd CLI and its commands can be found at GitHub.

  • 2. Register your Account & App

    Now, you have to register your account, create a passw0rd application and get application's credentials. Passw0rd CLI allows you to create and manage all those.

    First, register your account

    Specify your valid email:

    ./passw0rd account register [email protected]
    

    then, enter a confirmation code you got in the email and create your account password.

    Enter confirmation code:
    AAAAAAAA
    Enter account password:
    ***************
    Again:
    ***************
    

    Second, set up two-factor authentication (2FA)

    Once you confirm your account password, the passw0rd CLI immediately asks you to set up 2FA and create a new passw0rd App with its credentials. Press "y" to apply it:

    Your two-factor QR code URL (Authy or Google Auth):
    https://passw0rd.io/accounts/v1/qr/AAAAAAAAAAAAAAAAAAAAAA
    
    Would you like to create a default app and a client secret key right now? [y] y
    
    Enter your 2-factor code:
    ******
    
    Your app credentials:
    app_name: Passw0rd_App_11111111
    app_token: PT.100000001000000001010101
    service_public_key: PK.1.000+00000000000000DNU88u/GJwKC0REx3i/7vvWQZuH+000000000000/KVeg1N+000000=
    app_secret_key: SK.1.0000000000000gWsv/DLV3mJth000000000=
    
    • Copy a QR link that you got in a passw0rd CLI
    • Open the QR link in a browser or some other application
    • Scan the QR using your 2FA application
    • Enter a 2FA code into a passw0rd CLI

    Note! To set up 2FA you have to use an application that generates secure 2 step verification tokens on your device. For example, you can download and install Google Authenticator or Authy.

    As a result, you get your passw0rd's application credentials:

    • application name
    • application app_token
    • server service_public_key
    • client app_secret_key

    Please save them.

  • 3. Install and Configure SDK

    Install SDK Package

    # install Passw0rd Golang SDK library with the following code:
    go get -u github.com/VirgilSecurity/virgil-passw0rd-go
    
    # SDK uses Dep to do manage its dependencies.
    # More about the Dep: "https://golang.github.io/dep/docs/installation.html"
    
    # Please install Dep and run the following commands:
    cd $(go env GOPATH)/src/github.com/VirgilSecurity/virgil-passw0rd-go
    dep ensure
    

    Configure SDK

    // here set your passw0rd credentials
    import (
        "github.com/VirgilSecurity/virgil-passw0rd-go"
    )
    
    func InitPassw0rd() (*passw0rd.Protocol, error){
        appToken := "PT.0000000000lFPKdlSydN9BUrn5oEuDwf3Hqps"
        appSecretKey := "SK.1.00000000000000f1+MbEzpdtEP1kUefA0PUJw2UyI0="
        servicePublicKey := "PK.1.BEn/0000000000+kaRUZNvwQ/jkhDQdALrw6VdfvhZhPQQHWyYO+fRH3WxcZBjA0t000000000="
    
        context, err := passw0rd.CreateContext(appToken, servicePublicKey, appSecretKey, "")
        if err != nil{
            return nil, err
        }
    
        return passw0rd.NewProtocol(context)
    }
    
  • 4. Prepare Your Database

    The passw0rd SDK allows you to easily perform all the necessary operations to create, verify and update user's passw0rd record.

    Passw0rd record - a user's password that is protected with our Passw0rd technology. Passw0rd record contains version, client & server random salts and two values obtained during execution of the PHE protocol.

    In order to create and work with user's record, you need to add additional column to your database table.

    The column must have the following parameters:

    ParametersTypeSize (bytes)Description
    recordbytearray210A unique passw0rd's record, namely a user's protected passw0rd.
  • 5. Enroll User Record

    Use this flow to create a passw0rd's record in your DB for a user.

    Remember, if you already have a database with user passwords, you don't have to wait until a user logs in into your system to implement Passw0rd technology. You can go through your database and enroll (create) a user's record at any time.

    So, in order to create a record for a new database or available one, go through the following operations:

    • Take a user's password (or its hash or whatever you use) and pass it into the EnrollAccount function in a SDK on your Server side.
    • Passw0rd SDK will send a request to Passw0rd Service to get enrollment.
    • Then, Passw0rd SDK will create a user's record. You need to store this unique user's record in your database in associated column.
    package main
    
    import (
        "encoding/base64"
        "fmt"
        "github.com/VirgilSecurity/virgil-passw0rd-go"
        "github.com/VirgilSecurity/virgil-phe-go"
    )
    
    // create a new encrypted password record using user password or its hash
    func EnrollAccount(password string, prot *passw0rd.Protocol) error{
    
        record, encryptionKey, err := prot.EnrollAccount(password)
        if err != nil {
            return err
        }
    
        //save record to database
        fmt.Printf("Database record:\n%s\n", base64.StdEncoding.EncodeToString(record))
    
        //use encryptionKey for protecting user data
        encrypted, err := phe.Encrypt(data, encryptionKey)
        ...
    
    }
    

    When you've created passw0rd's records for all users in your DB, you can delete the unnecessary column where user passwords were previously stored.

  • 6. Verify User Record

    Use this flow when a user already has his or her own passw0rd's record in your database. This function allows you to verify user's password with the record from your DB every time when the user signs in. You have to pass his or her record from your DB into the VerifyPassword function:

    package main
    
    import (
        "fmt"
        "github.com/VirgilSecurity/virgil-passw0rd-go"
        "github.com/VirgilSecurity/virgil-phe-go"
    )
    
    
    func VerifyPassword(password string, record []byte, prot *passw0rd.Protocol) error{
        encryptionKey, err := prot.VerifyPassword(password, record)
        if err != nil {
    
            if err == passw0rd.ErrInvalidPassword{
                //invalid password
            }
            return err //some other error
        }
    
        //use encryptionKey for decrypting user data
        decrypted, err := phe.Decrypt(encrypted, encryptionKey)
        ...
    
    }
    
  • Encrypt User Data

    Not only user's password is a sensitive data. In this flow we will help you to protect any Personally identifiable information (PII) in your database.

    PII is a data that could potentially identify a specific individual, and PII can be sensitive. Sensitive PII is information which, when disclosed, could result in harm to the individual whose privacy has been breached. Sensitive PII should therefore be encrypted in transit and when data is at rest. Such information includes biometric information, medical information, personally identifiable financial information (PIFI) and unique identifiers such as passport or Social Security numbers.

    Passw0rd service allows you to protect user's PII (personal data) with a user's encryptionKey that is obtained from EnrollAccount or VerifyPassword functions. The encryptionKey will be the same for both functions.

    In addition, this key is unique to a particular user and won't be changed even after rotating (updating) the user's record. The encryptionKey will be updated after user changes own password.

    Here is an example of data encryption/decryption with an encryptionKey:

    package main
    
    import (
        "fmt"
        "github.com/VirgilSecurity/virgil-phe-go"
    )
    
    func main() {
    
        //key is obtained from proto.EnrollAccount() or proto.VerifyPassword() calls
    
        data := []byte("Personal data")
    
        ciphertext, err := phe.Encrypt(data, encryptionKey)
        if err != nil {
            panic(err)
        }
        decrypted, err := phe.Decrypt(ciphertext, encryptionKey)
        if err != nil {
            panic(err)
        }
    
        fmt.Println(decrypted)
    }
    

    Encryption is performed using AES256-GCM with key & nonce derived from the user's encryptionKey using HKDF and random 256-bit salt.

    Virgil Security has Zero knowledge about a user's encryptionKey, because the key is calculated every time when you execute EnrollAccount or VerifyPassword functions at your server side.

  • Rotate User Record

    This function allows you to use a special update_token to update all of the records in your database.

    There can never be enough security, so you should rotate your sensitive data regularly (about once a week). Use this flow to get an update_token for updating user's record in your database and to get a new app_secret_key and service_public_key of a specific application.

    Also, use this flow in case your database has been COMPROMISED!

    Note! This action doesn't require to create an additional table or modify scheme of existing table. When a user just needs to change his or her own password, use the EnrollAccount function to replace user's oldRecord value in your DB with a newRecord.

    Here is how it works:

    STEP 1. Get your update_token using Passw0rd CLI.

    Be sure you're logged in your passw0rd account. To log in the account use the following CLI command (2FA is required):

    ./passw0rd login [email protected]
    

    Then, use the rotate command and your application token to get an update_token:

    ./passw0rd application rotate <app_token>
    

    as a result, you get your update_token.

    STEP 2. Initialize passw0rd SDK with the update_token. Move to passw0rd SDK configuration file and specify your update_token:

    // here set your passw0rd credentials
    import (
        "github.com/VirgilSecurity/virgil-passw0rd-go"
    )
    
    func InitPassw0rd() (*passw0rd.Protocol, error){
        appToken := "PT.0000000irdopvijQlFPKdlSydN9BUrn5oEuDwf3Hqps"
        appSecretKey := "SK.1.000jofLr2JOu2Vf1+MbEzpdtEP1kUefA0PUJw2UyI0="
        servicePublicKey := "PK.1.BEn/hnuyKV0inZL+kaRUZNvwQ/jkhDQdALrw6Vdf00000QQHWyYO+fRlJYZweUz1FGH3WxcZBjA0tL4wn7kE0ls="
        updateToken := "UT.2.00000000+0000000000000000000008UfxXDUU2FGkMvKhIgqjxA+hsAtf17K5j11Cnf07jB6uVEvxMJT0lMGv00000="
    
        context, err := passw0rd.CreateContext(appToken, servicePublicKey, appSecretKey, updateToken)
        if err != nil{
            return nil, err
        }
    
        return passw0rd.NewProtocol(context)
    }
    

    STEP 3. Start migration. Use the RecordUpdater SDK class to create a user's newRecord (you don't need to ask your users to create a new password). The RecordUpdater requires the update_token and user's oldRecord from your DB:

    package main
    
    import (
        "crypto/subtle"
        "github.com/VirgilSecurity/virgil-phe-go"
    )
    
    func main(){
    
        // use NewRecordUpdater("UPDATE_TOKEN") function to create a class instance
        updater, err := passw0rd.NewRecordUpdater("UPDATE_TOKEN")
        if err != nil{
                //something went wrong
        }
    
        //for each record
        //get old record from the database
        oldRecord := ...
    
        //update old record
        newRecord, err := updater.UpdateRecord(oldRecord)
        if err != nil{
            //something went wrong
        }
    
        // newRecord is nil ONLY if oldRecord is already the latest version
        if newRecord != nil{
            //save new record to the database
            saveNewRecord(newRecord)
        }
    
    }
    

    So, run the RecordUpdater class and save user's newRecord into your database.

    Since the SDK is able to work simultaneously with two versions of user's records (newRecord and oldRecord), this will not affect the backend or users. This means, if a user logs into your system when you do the migration, the passw0rd SDK will verify his password without any problems because Passw0rd Service can work with both user's records (newRecord and oldRecord).

    STEP 4. Get a new app_secret_key and service_public_key of a specific application.

    Use passw0rd CLI update-keys command and your update_token to update the app_secret_key and service_public_key:

    ./passw0rd application update-keys <service_public_key> <app_secret_key> <update_token>
    

    STEP 5. Move to passw0rd SDK configuration and replace your previous app_secret_key, service_public_key with a new one (app_token will be the same). Delete update_token and previous app_secret_key, service_public_key.

    // here set your passw0rd credentials
    import (
        "github.com/VirgilSecurity/virgil-passw0rd-go"
    )
    
    func InitPassw0rd() (*passw0rd.Protocol, error){
        appToken := "APP_TOKEN_HERE"
        appSecretKey := "NEW_APP_SECRET_KEY_HERE"
        servicePublicKey := "NEW_SERVICE_PUBLIC_KEY_HERE"
    
        context, err := passw0rd.CreateContext(appToken, servicePublicKey, appSecretKey, "")
        if err != nil{
            return nil, err
        }
    
        return passw0rd.NewProtocol(context)
    }
    

frequently asked questions_