The bw2qr application, written in C++, enables users to convert a JSON vault file exported from Bitwarden or Vaultwarden into a printable PDF file. With its offline functionality, this C++ desktop application ensures enhanced security and data isolation, making it a reliable solution for securely storing passwords. The program utilizes QR Code with high redundancy mode for printing entries, offering the ability to recover damaged data, and verifies the validity of generated QR Code using the ZXing library.
This application incorporates the AES-256-CBC algorithm to encrypt the data of the QR Code when the --password command-line option is set. This encryption enhances the security by providing robust data protection. The password will be automatically hashed using SHA-256 algorithm to be used as the cipher key.
See an example of PDF file generated with QR Codes:
Notes: the AES-256-GCM hasn't been chosen as the default algorithm to encrypt data, besides the fact that it allows authentication and is even more robust because there aren't many websites/applications available to decrypt it easily.
Implemented in c++17 and use vcpkg/cmake for the build-system.
It uses the winpp header-only library from: https://github.com/strinque/winpp.
When it comes to handling passwords and vaults, it is crucial to prioritize security and avoid trusting any applications or websites that may compromise your credentials. The bw2qr application prioritizes security by operating in full offline mode by default, eliminating the risk of interception or unauthorized storage. However, if you specify the command-line option --frame-logo-size 64, it will try to download the favicon and position it at the center of the QR Code.
List of C++ open-source libraries used:
- use
winppto handle command-line argument variables - use
nlohmann/jsonheader-only library forjsonparsing - use
cpp-httplibto get the favicon of websites to add them in the QR Code - use
nayuki-qr-code-generatorto generate QR Code - use
graphicsmagickto create QR Code png image and frame - use
PoDoFoto create thepdffile - use
ZXingto check the validity of the QR Code - use
opensslto encrypt QR Code with AES 256 CBC algorithm
The program reads a bitwarden or vaultwarden json file and export specific entries that are tagged as favorite = true into QR Code exported in a pdf file. The exported entries include important login information such as username, password, authenticator key, and custom fields.
The QR Code algorithm version: 25 of size: 117x117 with ecc: quartile (up to 25% of redondancy) has been chosen. Thus, the maximum size of data that can be embedded = 715 bytes (or 527 bytes when encrypted (base64 encoding of aes-block-size of 16 bytes)).
Once the QR Code is scanned, it can be read as text and includes all of the important login information in a json readable format.
For example:
{
"login": {
"username": "username-chrome",
"password": "password-chrome",
"totp": "",
},
"fields": [
{ "editor": "google" }
]
}To decrypt an encrypted QR Code with AES-256-CBC algorithm (when a password has been set), prefer using an offline application such as Crypto - Encryption Tools on android. Otherwise, use the following websites which decrypt in the browser without any server interaction:
To create the SHA-256 key from your password, use the following website:
Example of the same "chrome" entry encrypted in QR Code with --password "password":
Y7mU2KOylYh2gcsGc8PkqJzGbefDbYFXYZea2Ys5RNzKomRvOlqIDUQ6fzLX3+q7LyLudRyDqktwJzNucWMQH+m8IocMEUUj/wnzAx94mvC8rXE5mBPdQGu0vV4A8VqRUgV2h/BahmO3Zei0EJEWOspKk0li8vqn1wLJilBD369JfagsIm8oKkmwnF7cgTYUtMz1a1V+a4wFhw3WCnE34SBgfBLEcyvvhjurWRiy+ThMbs7qVWm2OYes/4DzmCm8FM48W0jd45fyVQG2pZepfUnBDTy3Z30iemnXL/5MwGnQb6s3hl44NQv26VaSthK4Ki0MmiOCAPngpobWpMZL1/QijE8dByXerfy8snaf+Unw/qW2rnjzeuoQvkLVocvmau5MtaVgTz+sHWsCXuLQXyy3uxoqCKTkFAuk5I/hCVLT5NVHWJDlW85UsRKHfDeEWvtyVj+W9KiINWn1nXD3xANsAWNVxwKDRpxPYc3HnqZW1MhlyaAUOANRO6jd+gnMZMKc9CVPebBD9RSNcvyHySCD8bpuLJH06XXD2Erq/FiK+IENFd+mec4RNwIfV1vJ0LWlbUA2t/RJm8GVv0teona3cRfoSDniEz4lr5tLHo40q6OA96vuY2xuv5veYI2NgodV734gMTJ+RqKgV7Rbs3lVsoqYN0gO+FZ7b43IN6JzLj06QVLRqlw2SFcHb+rG
15a0e0e2cbb03cbc7900b80fa8169156
SHA-256 hash of password:
5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8
| Settings | Value |
|---|---|
| Algorithm | AES-256-CBC |
| Data | Copy scanned QR Code data as base64 |
| Padding | None |
| Key Size | 256 |
| Key Hash | SHA-256 of password |
| IV | Copy scanned QR Code of IV HEX |
When it comes to handling passwords and vaults, it is crucial to prioritize security and avoid trusting any applications or websites that may compromise your credentials. The bw2qr application prioritizes security by operating in full offline mode by default, eliminating the risk of interception or unauthorized storage. However, if you specify the command-line option --frame-logo-size 64, it will try to download the favicon and position it at the center of the qrcode.
Arguments:
--json: path to the bitwarden json file [mandatory]--pdf: path to the pdf output file [mandatory]--password: set a password to encrypt QR Code data using AES-256-CBC--qrcode-module-px-size: size in pixels of each QR Code module (default: 3)--qrcode-border-px-size: size in pixels of the QR Code border (default: 2)--qrcode-module-color: QR Code module color (default: black)--qrcode-background-color: QR Code background color (default: white)--frame-border-color: color of the frame (default: #054080)--frame-border-width-size: size in pixels of the frame border width (default: 12)--frame-border-height-size: size in pixels of the frame border height (default: 65)--frame-border-radius: size in pixels of the frame border radius (default: 15)--frame-logo-size: size in pixels of the logo (default: 0)--frame-font-family: font family of the QR Code name (default: Arial-Black)--frame-font-color: font color of the QR Code name (default: white)--frame-font-size: size in pixels of the QR Code name font (default: 28)--pdf-cols: number of columns of QR Codes in pdf (default: 4)--pdf-rows: number of rows of QR Codes in pdf (default: 5)
bw2qr.exe --json bitwarden.json \
--pdf file.pdf \
--frame-logo-size 64This project uses vcpkg, a free C/C++ package manager for acquiring and managing libraries to build all the required libraries.
It also needs the installation of the winpp, a private header-only library, inside vcpkg.
The install procedure can be found in: https://vcpkg.io/en/getting-started.html.
The following procedure installs vcpkg and integrates it in Visual Studio.
Open PowerShell:
cd c:\
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
.\bootstrap-vcpkg.bat
.\vcpkg.exe integrate installCreate a x64-windows-static-md triplet file used to build the program in shared-mode for Windows CRT libraries but static-mode for third-party libraries:
$VCPKG_DIR = Get-Content "$Env:LocalAppData/vcpkg/vcpkg.path.txt" -Raw
Set-Content "$VCPKG_DIR/triplets/community/x64-windows-static-md.cmake" 'set(VCPKG_TARGET_ARCHITECTURE x64)
set(VCPKG_CRT_LINKAGE dynamic)
set(VCPKG_LIBRARY_LINKAGE static)
set(VCPKG_BUILD_TYPE release)'Copy the vcpkg ports files from winpp header-only library repository to the vcpkg directory.
$VCPKG_DIR = Get-Content "$Env:LocalAppData/vcpkg/vcpkg.path.txt" -Raw
mkdir $VCPKG_DIR/ports/winpp
Invoke-WebRequest -Uri "https://raw.githubusercontent.com/strinque/winpp/master/vcpkg/ports/winpp/portfile.cmake" -OutFile "$VCPKG_DIR/ports/winpp/portfile.cmake"
Invoke-WebRequest -Uri "https://raw.githubusercontent.com/strinque/winpp/master/vcpkg/ports/winpp/vcpkg.json" -OutFile "$VCPKG_DIR/ports/winpp/vcpkg.json"To build the program with vcpkg and cmake, follow these steps:
$VCPKG_DIR = Get-Content "$Env:LocalAppData/vcpkg/vcpkg.path.txt" -Raw
git clone ssh://[email protected]:1863/git/bw2qr.git
cd bw2qr
mkdir build; cd build
cmake -DCMAKE_BUILD_TYPE="MinSizeRel" `
-DVCPKG_TARGET_TRIPLET="x64-windows-static-md" `
-DCMAKE_TOOLCHAIN_FILE="$VCPKG_DIR/scripts/buildsystems/vcpkg.cmake" `
../
cmake --build . --config MinSizeRelThe program executable should be compiled in: bw2qr\build\src\MinSizeRel\bw2qr.exe.
Microsoft Visual Studio can automatically install required vcpkg libraries and build the program thanks to the pre-configured files:
CMakeSettings.json: debug and release settingsvcpkg.json: libraries dependencies
The following steps needs to be executed in order to build/debug the program:
File => Open => Folder...
Choose bw2qr root directory
Solution Explorer => Switch between solutions and available views => CMake Targets View
Select x64-release or x64-debug
Select the src\bw2qr.exe (not bin\bw2qr.exe)To add command-line arguments for debugging the program:
Solution Explorer => Project => (executable) => Debug and Launch Settings => src\program.exe
"args": [
"--json \"${ProjectDir}\\model\\bitwarden.json\"",
"--pdf \"${ProjectDir}\\model\\file.pdf\"",
"--qrcode-module-px-size 3",
"--qrcode-border-px-size 2",
"--qrcode-module-color \"black\"",
"--qrcode-background-color \"white\"",
"--frame-border-color \"#054080\"",
"--frame-border-width-size 12",
"--frame-border-height-size 65",
"--frame-border-radius 15",
"--frame-logo-size 64",
"--frame-font-family \"Arial-Black\"",
"--frame-font-color \"white\"",
"--frame-font-size 28.0",
"--pdf-cols 4",
"--pdf-rows 5"
]