Compare commits
138 Commits
2021Export
...
2023Export
| Author | SHA1 | Date | |
|---|---|---|---|
| d249b9241e | |||
| fc80eaab16 | |||
| 9f73fee228 | |||
|
|
4118a8d077 | ||
| 72df3e504a | |||
| 04ad1dbba6 | |||
| 1e4ed58fe6 | |||
| 75562c141f | |||
| f9bef2bce2 | |||
| 8938c0378a | |||
| 0023557177 | |||
| 3baac3958b | |||
| c00c7ba4ec | |||
| 9359b36c6f | |||
| 5ed4f3da76 | |||
| 7ec0116fa5 | |||
| 8f8746e4fa | |||
| ad035cae11 | |||
| 1284693cf7 | |||
| 70c07fb605 | |||
| af3128c7f7 | |||
| d52abb2a4d | |||
| 946d627482 | |||
| 183aadf796 | |||
| 305d7f9019 | |||
| 4ac0a2db37 | |||
| b1077dc4be | |||
| c2e3c37e24 | |||
| 859ccb675f | |||
| e6dbe90d81 | |||
|
|
70a4bb41a0 | ||
|
|
6cab1b4573 | ||
|
|
9e43bc7126 | ||
|
|
58a7b002ba | ||
|
|
79d56d00d0 | ||
|
|
c0890fd57d | ||
|
|
88268d4889 | ||
|
|
303e11b348 | ||
|
|
add98a058f | ||
|
|
824eb2488d | ||
|
|
fddaf8ac15 | ||
|
|
7be43da4c0 | ||
| 5032946e14 | |||
| a5ca8d2207 | |||
| 641ffacfb4 | |||
| addf7f27c4 | |||
| 5f95747b05 | |||
| afdbaa0ae7 | |||
|
|
07a38c93e6 | ||
|
|
5ec6f2b415 | ||
|
|
60e19cc718 | ||
|
|
ed5ba18ca7 | ||
|
|
892e8548b9 | ||
|
|
e249901af1 | ||
|
|
d410ff8aad | ||
|
|
d11baaff9c | ||
|
|
de32b4c6e6 | ||
|
|
7c37b9bb3e | ||
|
|
3d60dcdcb2 | ||
|
|
b2a8ea6f71 | ||
|
|
248aa408ba | ||
|
|
acbcfa1c1d | ||
|
|
d25282a6fd | ||
|
|
6ce71bbd61 | ||
|
|
a4bac299ac | ||
|
|
70aa686988 | ||
|
|
f22321e226 | ||
|
|
75dfd0c758 | ||
|
|
dab4eaa585 | ||
|
|
f9189ee111 | ||
|
|
8de62c4b5d | ||
|
|
a8cb3ca250 | ||
|
|
d684cd0360 | ||
|
|
503e5bce53 | ||
|
|
e16cd74e4d | ||
|
|
469c838447 | ||
|
|
710359b324 | ||
|
|
90268494a7 | ||
|
|
142eb62ea4 | ||
| ae59d4975e | |||
| 6ac6337b86 | |||
| 77d8d51540 | |||
| 3b51a9a065 | |||
| 71187689a9 | |||
| 8d77101cc2 | |||
| 9fa801908d | |||
| 171d5617b2 | |||
| 5c7b348b1b | |||
| 5958bfdd55 | |||
| 7d9e4fa428 | |||
|
|
ea90c0dc97 | ||
|
|
f823711817 | ||
|
|
247615d3d1 | ||
|
|
0cf3109b18 | ||
|
|
de945f6668 | ||
|
|
564e5f96bf | ||
|
|
9add8abcbf | ||
|
|
fdc92823c7 | ||
|
|
a113fc49f5 | ||
| 10da1b57e7 | |||
| cefecdfd3b | |||
| cfc821fa46 | |||
| 8beb0a56a9 | |||
| 42ef3870d9 | |||
| 662fc604cd | |||
| a793b91bb3 | |||
| 8c2714a9d6 | |||
| e850610128 | |||
| 5db8ed9259 | |||
| baca57dd2b | |||
| 5f3e7e0c1a | |||
| bd2cbc643e | |||
| 70920467e8 | |||
| d406f89835 | |||
| 2abcdbc50e | |||
| 8b7b83ee99 | |||
| fcac9fb9b7 | |||
| a409873f6b | |||
| e2579b4057 | |||
| 4af65b85e4 | |||
| 1bc05527d4 | |||
| 55b8e792ae | |||
| 307eaa2a38 | |||
| 5c3b342c88 | |||
| 9e64f093ac | |||
| 86e16e64ee | |||
| 62a82ca818 | |||
| 541ce541c9 | |||
| ee513a5e0e | |||
| c9546e3b91 | |||
| 3649ca2167 | |||
| 8481a48aa0 | |||
| 1f97bbe182 | |||
| fc2d98306a | |||
| ecccbc8226 | |||
| 8cfb8f741b | |||
| 1e6f5c37a8 | |||
| 02a247b61b |
133
.gitignore
vendored
133
.gitignore
vendored
@@ -1,9 +1,138 @@
|
||||
# ---> Python
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
.python-version
|
||||
|
||||
# celery beat schedule file
|
||||
celerybeat-schedule
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# config file
|
||||
*config.yml
|
||||
*config.py
|
||||
*config.ini
|
||||
*config.json
|
||||
|
||||
# config/secret/certs files
|
||||
*.key
|
||||
*.crt
|
||||
*secrets.ini
|
||||
*client.conf
|
||||
*.config
|
||||
|
||||
# GPG files #
|
||||
*.gpg
|
||||
*.asc
|
||||
*.pgp
|
||||
*.age
|
||||
*.csv
|
||||
*.json
|
||||
*.zip
|
||||
attachments/
|
||||
attachments/
|
||||
lib/gpg/home/
|
||||
working/
|
||||
exports/
|
||||
@@ -10,4 +10,4 @@ Options:
|
||||
-zip Zips the export/attachements into a zip
|
||||
-encrypt Encrypts the zip file with gpg symmetric encryption using your vault password
|
||||
-verbose Show verbose information
|
||||
```
|
||||
```
|
||||
@@ -6,93 +6,154 @@ param (
|
||||
|
||||
# Verbose output
|
||||
if ($verbose) {
|
||||
$oldverbose = $VerbosePreference
|
||||
$VerbosePreference = "continue"
|
||||
}
|
||||
|
||||
# get the date/time for the back filename
|
||||
$dateTime = get-date -format ("yyyyMMdd-HHmmss")
|
||||
$env:Path += ";$PSScriptRoot\lib;$PSScriptRoot\lib\gpg\bin;$PSScriptRoot\lib\age"
|
||||
$dateTime = Get-Date -format ("yyyyMMdd-HHmmss")
|
||||
# set the binaries path, do not rely on the path variables as they are not hashed
|
||||
$bw = "$PSScriptRoot\lib\bw.exe"
|
||||
$gpg = "$PSScriptRoot\lib\gpg\bin\gpg.exe"
|
||||
$sdelete = "$PSScriptRoot\lib\sdelete.exe"
|
||||
|
||||
bw config server https://bitwarden.johnhgaunt.com
|
||||
# set bitwarden server to my self hosted instance
|
||||
#& $bw config server https://bitwarden.johnhgaunt.com
|
||||
|
||||
# begin while loop to login, if login is incorrect, ask user again
|
||||
while ($true) {
|
||||
$username = Read-Host "Please enter your bitwarden email"
|
||||
$password = Read-Host -assecurestring "Please enter your bitwarden password"
|
||||
$password = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($password))
|
||||
$code = Read-Host "Please enter your 2fa code (hit enter if not used)"
|
||||
if ($code -eq "") {
|
||||
$sessionKey = $(bw login $username $password --raw --nointeraction)
|
||||
} else {
|
||||
$sessionKey = $(bw login $username $password --method 0 --code $code --raw --nointeraction)
|
||||
}
|
||||
$bwStatus = $(ConvertFrom-Json $(bw status))
|
||||
if ($bwStatus.Status -ne "locked") {
|
||||
# just writing a new line
|
||||
Write-Host " "
|
||||
Write-Warning "Unable to login, please try agian."
|
||||
} else {
|
||||
# ask for api client id/secret and password
|
||||
$clientID = Read-Host "Please enter your Bitwarden API client_id"
|
||||
$env:BW_CLIENTID = "$clientID"
|
||||
$clientSecret = Read-Host -assecurestring "Please enter your bitwarden API client_secret"
|
||||
$clientSecret = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($clientSecret))
|
||||
$env:BW_CLIENTSECRET = "$clientSecret"
|
||||
# test login
|
||||
& $bw login --apikey --raw
|
||||
$bwStatus = $(ConvertFrom-Json $(& $bw status))
|
||||
if ($bwStatus."Status" -eq "locked") {
|
||||
# Authentication was successful
|
||||
# start new loop for password unlock
|
||||
while ($true) {
|
||||
$password = Read-Host -assecurestring "Please enter your Bitwarden password"
|
||||
$password = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($password))
|
||||
$sessionKey = $(& $bw unlock $password --raw --nointeraction)
|
||||
# get the bw status to see if the login was successfull and inform user
|
||||
$bwStatus = $(ConvertFrom-Json $(& $bw status --session $sessionKey))
|
||||
if ($bwStatus."Status" -eq "unlocked") {
|
||||
$username = $bwStatus."userEmail"
|
||||
break
|
||||
} else {
|
||||
# just writing a new line
|
||||
Write-Host " "
|
||||
Write-Warning "Unable to unlock your vault, please try agian."
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
} else {
|
||||
Write-Host " "
|
||||
Write-Warning "Unable to authenticate, please try agian."
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Export the vault to both CSV and JSON files, this allows best compatibility to import again or switch managers.
|
||||
Write-Host "Exporting vault to both CSV and JSON files."
|
||||
Write-Verbose "Exporting vault to CSV."
|
||||
bw export $password --output "$PSScriptRoot\Bitwarden User $username Export $dateTime.csv" --format csv --session $sessionKey
|
||||
& $bw export $password --output "$PSScriptRoot\Bitwarden User $username Export $dateTime.csv" --format csv --session $sessionKey
|
||||
# just writing a new line
|
||||
Write-Host " "
|
||||
Write-Verbose "Exporting vault to JSON."
|
||||
bw export $password --output "$PSScriptRoot\Bitwarden User $username Export $dateTime.json" --format json --session $sessionKey
|
||||
& $bw export $password --output "$PSScriptRoot\Bitwarden User $username Export $dateTime.json" --format json --session $sessionKey
|
||||
# just writing a new line
|
||||
Write-Host " "
|
||||
|
||||
# look for organizations
|
||||
Write-Host "Looking for Organizations..."
|
||||
$organizations = $(ConvertFrom-Json $(bw list organizations --session $sessionKey))
|
||||
Write-Host "Found $(($organizations | measure).count) Organiztaions."
|
||||
$organizations = $(ConvertFrom-Json $(& $bw list organizations --session $sessionKey))
|
||||
Write-Host "Found $(($organizations | Measure-Object).count) Organiztaions."
|
||||
|
||||
$organizations | foreach {
|
||||
# loop through the found organizations and again export both as CSV and JSON for best compatibility
|
||||
$organizations | ForEach-Object {
|
||||
Write-Host "Exporting organization $($_.name) vault to both CSV and JSON files."
|
||||
Write-Verbose "Exporting organization vault to CSV."
|
||||
bw export $password --organizationid $_.id --output "$PSScriptRoot\Bitwarden Organization $($_.name) Export $dateTime.csv" --format csv --session $sessionKey
|
||||
& $bw export $password --organizationid $_.id --output "$PSScriptRoot\Bitwarden Organization $($_.name) Export $dateTime.csv" --format csv --session $sessionKey
|
||||
# just writing a new line
|
||||
Write-Host " "
|
||||
Write-Verbose "Exporting organization vault to JSON."
|
||||
bw export $password --organizationid $_.id --output "$PSScriptRoot\Bitwarden Organization $($_.name) Export $dateTime.json" --format json --session $sessionKey
|
||||
& $bw export $password --organizationid $_.id --output "$PSScriptRoot\Bitwarden Organization $($_.name) Export $dateTime.json" --format json --session $sessionKey
|
||||
# just writing a new line
|
||||
Write-Host " "
|
||||
}
|
||||
|
||||
# find all items with attachments
|
||||
Write-Host "Looking for items with attachments..."
|
||||
$itemsWithAttachments = $((ConvertFrom-Json $(bw list items --session $sessionKey)) | Where-Object attachments)
|
||||
Write-Host "Found $(($itemsWithAttachments | measure).count) items with attachments."
|
||||
$itemsWithAttachments = $((ConvertFrom-Json $(& $bw list items --session $sessionKey)) | Where-Object attachments)
|
||||
Write-Host "Found $(($itemsWithAttachments | Measure-Object).count) items with attachments."
|
||||
|
||||
# loop through all the items with attachments and download them into a folder with the name of the item
|
||||
Write-Host "Downloading attachments..."
|
||||
$itemsWithAttachments | foreach {
|
||||
$itemsWithAttachments | ForEach-Object {
|
||||
Write-Verbose "Working on item $($_.name) ($($_.id))."
|
||||
$folder="$PSScriptRoot\attachments\$($_.name)"
|
||||
$itemID=$_.id
|
||||
$_.attachments | foreach {
|
||||
$_.attachments | ForEach-Object {
|
||||
Write-Verbose "Downloading attachment ($($_.id)) with name $($_.fileName) to $folder."
|
||||
bw get attachment $_.id --itemid $itemID --output "$folder\$($_.fileName)" --session $sessionKey
|
||||
& $bw get attachment $_.id --itemid $itemID --output "$folder\$($_.fileName)" --session $sessionKey
|
||||
# just writing a new line
|
||||
Write-Host " "
|
||||
sleep -Milliseconds 500
|
||||
Start-Sleep -Milliseconds 500
|
||||
}
|
||||
}
|
||||
|
||||
# zip file name used below
|
||||
$zipFilename = "Bitwarden Backup $dateTime.zip"
|
||||
|
||||
# if the user wants the export zipped or encrypted
|
||||
if ($zip -or $encrypt) {
|
||||
# zip the export
|
||||
Write-Host "Zipping the backup together..."
|
||||
Compress-Archive -Path $PSScriptRoot\*.csv, $PSScriptRoot\*.json, $PSScriptRoot\attachments -DestinationPath "$PSScriptRoot\$zipFilename"
|
||||
# securely delete the export items with sdelete
|
||||
Write-Host "Securely deleting the exports and attachments..."
|
||||
sdelete64.exe -s -p 25 $PSScriptRoot\*.csv $PSScriptRoot\*.json $PSScriptRoot\attachments
|
||||
& $sdelete -s -p 25 $PSScriptRoot\*.csv $PSScriptRoot\*.json $PSScriptRoot\attachments
|
||||
|
||||
# if encrypting the export
|
||||
if ($encrypt) {
|
||||
# encrypt the zip export with gpg
|
||||
Write-Host "Encrypting the backup zip with your bitwarden password..."
|
||||
gpg.exe --batch --passphrase "$password" --symmetric --cipher-algo AES256 --digest-algo SHA512 --compression-algo Uncompressed --output "$PSScriptRoot\$zipFilename.gpg" "$PSScriptRoot\$zipFilename"
|
||||
& $gpg --no-options --batch --passphrase "$password" --symmetric --cipher-algo AES256 --digest-algo SHA512 --compression-algo Uncompressed --output "$PSScriptRoot\$zipFilename.gpg" "$PSScriptRoot\$zipFilename"
|
||||
# securely delete the zip export with sdelete
|
||||
Write-Host "Securely deleting the zip file..."
|
||||
sdelete64.exe -p 25 "$PSScriptRoot\$zipFilename"
|
||||
& $sdelete -p 25 "$PSScriptRoot\$zipFilename"
|
||||
}
|
||||
}
|
||||
|
||||
# logout of bitwaren to ensure the session is destroyed
|
||||
& $bw logout
|
||||
# remove all the variables
|
||||
Remove-Variable -Name * -ErrorAction SilentlyContinue
|
||||
bw logout
|
||||
|
||||
|
||||
|
||||
<#
|
||||
|
||||
# Restore of attachements
|
||||
|
||||
cd C:\users\jgaunt\Git\bitwardenbackup\attachments
|
||||
|
||||
bw status
|
||||
|
||||
$folders = Get-childItem -Directory
|
||||
$items = bw list items | convertfrom-json
|
||||
$array = @()
|
||||
foreach ($folder in $folders) {
|
||||
foreach ($item in $items) {
|
||||
if ($folder.name -eq $item.name -and $item.type -gt 1) {
|
||||
#$array += bw get item $item.id | convertfrom-json
|
||||
$attachements = Get-ChildItem $folder
|
||||
foreach ($attachement in $attachements) {
|
||||
bw create attachment --file "$($attachement.FullName)" --itemid $item.id
|
||||
}
|
||||
Remove-Item -Recurse $folder
|
||||
}
|
||||
}
|
||||
}
|
||||
#>
|
||||
567
bitwardenBackup.py
Normal file
567
bitwardenBackup.py
Normal file
@@ -0,0 +1,567 @@
|
||||
# library needed
|
||||
import sys
|
||||
import os
|
||||
import subprocess
|
||||
import platform
|
||||
import json
|
||||
import getpass
|
||||
import logging
|
||||
import secrets
|
||||
import base64
|
||||
import optparse
|
||||
import hmac as pyhmac
|
||||
import datetime
|
||||
import time
|
||||
import shutil
|
||||
from kmip.core import enums
|
||||
from kmip.pie import client
|
||||
|
||||
def build_logger(level):
|
||||
logger = logging.getLogger()
|
||||
logger.setLevel(level)
|
||||
formatter = logging.Formatter(
|
||||
'%(asctime)s - %(levelname)s - %(message)s'
|
||||
)
|
||||
# log to file
|
||||
fileHandler = logging.FileHandler(log_file)
|
||||
fileHandler.setFormatter(formatter)
|
||||
logger.addHandler(fileHandler)
|
||||
# log to console
|
||||
consoleHandler = logging.StreamHandler()
|
||||
consoleHandler.setFormatter(formatter)
|
||||
logger.addHandler(consoleHandler)
|
||||
|
||||
return logger
|
||||
|
||||
def write_config_file(array, config_file):
|
||||
logger.debug("Starting to write config file and encrypt contents")
|
||||
logger.debug("Using config file: {}".format(config_file))
|
||||
logger.debug("Converting config from array to json")
|
||||
array_json = json.dumps(array)
|
||||
logger.debug("Encrypting config json")
|
||||
encrypted_array_json = encrypt(array_json)
|
||||
logger.debug("Attempting to write encrypted config to file")
|
||||
try:
|
||||
f = open(config_file, "w")
|
||||
f.write(encrypted_array_json)
|
||||
f.close()
|
||||
logger.debug("Successfully wrote encrypted config to file")
|
||||
except Exception as e:
|
||||
logger.error("Unable to write encrypted config to file. Error: {}".format(e))
|
||||
sys.exit(-1)
|
||||
logger.debug("Finshed writing config file and encrypting contents")
|
||||
|
||||
def read_config_file(config_file):
|
||||
logger.debug("Starting to read config file and decrypt contents")
|
||||
logger.debug("Using config file: {}".format(config_file))
|
||||
logger.debug("Attempting to read encrypted config from file")
|
||||
try:
|
||||
with open(config_file) as f:
|
||||
config = f.read()
|
||||
logger.debug("Successfully read encrypted config from file")
|
||||
except Exception as e:
|
||||
logger.error("Unable to read encrypted config from file. Error: {}".format(e))
|
||||
sys.exit(-1)
|
||||
logger.debug("Decrypting config contents")
|
||||
decrypted_array_json = decrypt(config)
|
||||
logger.debug("Convert config from json to array")
|
||||
array = json.loads(decrypted_array_json)
|
||||
logger.debug("Finished reading config file and decrypting contents")
|
||||
return array
|
||||
|
||||
def ask_for_confirmation(question):
|
||||
logger.debug("Asking user for confirmation")
|
||||
logger.debug("Question: {}".format(question))
|
||||
print(question)
|
||||
while True:
|
||||
confirmation = input("y/n> ")
|
||||
logger.debug("User answered: {}".format(confirmation))
|
||||
if confirmation.casefold() == "y":
|
||||
return True
|
||||
elif confirmation.casefold() == "n":
|
||||
return False
|
||||
else:
|
||||
print("This value must be one of the following characters: y, n.")
|
||||
|
||||
def create_encryption_key():
|
||||
# Create an encryption key.
|
||||
try:
|
||||
key_id = client.create(
|
||||
enums.CryptographicAlgorithm.AES,
|
||||
256,
|
||||
cryptographic_usage_mask=[
|
||||
enums.CryptographicUsageMask.ENCRYPT,
|
||||
enums.CryptographicUsageMask.DECRYPT
|
||||
]
|
||||
)
|
||||
logger.debug("Successfully created a new encryption key.")
|
||||
logger.debug("Encryption Key ID: {}".format(key_id))
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
sys.exit(-1)
|
||||
|
||||
# Activate the encryption key so that it can be used.
|
||||
try:
|
||||
client.activate(key_id)
|
||||
logger.debug("Successfully activated the encryption key.")
|
||||
return key_id
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
sys.exit(-1)
|
||||
|
||||
def create_hmac_key():
|
||||
# Create an encryption key.
|
||||
try:
|
||||
key_id = client.create(
|
||||
enums.CryptographicAlgorithm.AES,
|
||||
256,
|
||||
cryptographic_usage_mask=[
|
||||
enums.CryptographicUsageMask.MAC_GENERATE,
|
||||
enums.CryptographicUsageMask.MAC_VERIFY
|
||||
]
|
||||
)
|
||||
logger.debug("Successfully created a new HMAC key.")
|
||||
logger.debug("HMAC Key ID: {}".format(key_id))
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
sys.exit(-1)
|
||||
|
||||
# Activate the HMAC key so that it can be used.
|
||||
try:
|
||||
client.activate(key_id)
|
||||
logger.debug("Successfully activated the HMAC key.")
|
||||
return key_id
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
sys.exit(-1)
|
||||
|
||||
def encrypt(data):
|
||||
try:
|
||||
data = data.encode('UTF-8')
|
||||
key_id = create_encryption_key()
|
||||
iv = secrets.token_bytes(16)
|
||||
cipher_text, autogenerated_iv = client.encrypt(
|
||||
data,
|
||||
uid=key_id,
|
||||
cryptographic_parameters={
|
||||
'cryptographic_algorithm':
|
||||
enums.CryptographicAlgorithm.AES,
|
||||
'block_cipher_mode': enums.BlockCipherMode.CBC,
|
||||
'padding_method': enums.PaddingMethod.ANSI_X923
|
||||
},
|
||||
iv_counter_nonce=(
|
||||
iv
|
||||
)
|
||||
)
|
||||
hmac_key_id, hmac = client.mac(
|
||||
key_id.encode() + iv + cipher_text,
|
||||
uid = create_hmac_key(),
|
||||
algorithm = enums.CryptographicAlgorithm.HMAC_SHA512
|
||||
)
|
||||
logger.debug("Successfully encrypted the data.")
|
||||
array = dict()
|
||||
array['version'] = 1
|
||||
array['cipher_key_id'] = key_id
|
||||
array['cipher_text'] = base64.b64encode(cipher_text).decode()
|
||||
array['iv'] = base64.b64encode(iv).decode()
|
||||
array['hmac_key_id'] = hmac_key_id
|
||||
array['hmac'] = base64.b64encode(hmac).decode()
|
||||
logger.debug("Dict of info: {}".format(array))
|
||||
array_json = json.dumps(array)
|
||||
array_json_b64 = base64.b64encode(array_json.encode('utf-8')).decode()
|
||||
return array_json_b64
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
|
||||
def decrypt(data):
|
||||
array_json = base64.b64decode(data)
|
||||
array = json.loads(array_json)
|
||||
if array['version'] == 1:
|
||||
return decrypt_v1(array)
|
||||
else:
|
||||
logger.error("Unable to detemine encryption version.")
|
||||
return False
|
||||
|
||||
def decrypt_v1(array):
|
||||
try:
|
||||
logger.debug("Dict of info: {}".format(array))
|
||||
key_id = array['cipher_key_id']
|
||||
iv = base64.b64decode(array['iv'])
|
||||
cipher_text = base64.b64decode(array['cipher_text'])
|
||||
hmac_key_id = array['hmac_key_id']
|
||||
hmac = base64.b64decode(array['hmac'])
|
||||
hmac_key_id_test, hmac_test = client.mac(
|
||||
key_id.encode() + iv + cipher_text,
|
||||
uid = hmac_key_id,
|
||||
algorithm = enums.CryptographicAlgorithm.HMAC_SHA512
|
||||
)
|
||||
if pyhmac.compare_digest(hmac, hmac_test):
|
||||
logger.debug("HMAC matches.")
|
||||
else:
|
||||
logger.error("HMAC does not match, data is corrupted/tampered.")
|
||||
sys.exit(-1)
|
||||
plain_text = client.decrypt(
|
||||
cipher_text,
|
||||
uid=key_id,
|
||||
cryptographic_parameters={
|
||||
'cryptographic_algorithm':
|
||||
enums.CryptographicAlgorithm.AES,
|
||||
'block_cipher_mode': enums.BlockCipherMode.CBC,
|
||||
'padding_method': enums.PaddingMethod.ANSI_X923
|
||||
},
|
||||
iv_counter_nonce=(
|
||||
iv
|
||||
)
|
||||
)
|
||||
logger.debug("Successfully decrypted the data.")
|
||||
plain_text = plain_text.decode('utf-8')
|
||||
return plain_text
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
|
||||
def new_account_details():
|
||||
print("Requesting account details to add to config.")
|
||||
account_email_address = input("Please enter Bitwarden account email address: ")
|
||||
account_api_client_id = input("Please enter Bitwarden account API client ID: ")
|
||||
while True:
|
||||
account_api_secret = getpass.getpass("Please enter Bitwarden account API secret: ")
|
||||
account_api_secret2 = getpass.getpass("Please confirm Bitwarden account API secret: ")
|
||||
if account_api_secret == account_api_secret2:
|
||||
break
|
||||
else:
|
||||
print("The Bitwarden account API secrets do not match, please try again.")
|
||||
while True:
|
||||
account_vault_password = getpass.getpass("Please enter Bitwarden account vault password: ")
|
||||
account_vault_password2 = getpass.getpass("Please confirm Bitwarden account vault password: ")
|
||||
if account_vault_password == account_vault_password2:
|
||||
break
|
||||
else:
|
||||
print("The Bitwarden account vault passwords do not match, please try again.")
|
||||
|
||||
array = dict()
|
||||
array[account_email_address] = dict()
|
||||
array[account_email_address]["account_api_client_id"] = account_api_client_id
|
||||
array[account_email_address]["account_api_secret"] = account_api_secret
|
||||
array[account_email_address]["account_vault_password"] = account_vault_password
|
||||
return array
|
||||
|
||||
def edit_account_details(accounts, email):
|
||||
if ask_for_confirmation("Would you like to edit the Bitwarden account email address?\nCurrent Value: {}".format(email)):
|
||||
account_email_address = input("Please enter Bitwarden account email address: ")
|
||||
else:
|
||||
account_email_address = email
|
||||
|
||||
if ask_for_confirmation("Would you like to edit the Bitwarden account API client ID?\nCurrent Value: {}".format(accounts[email]['account_api_client_id'])):
|
||||
account_api_client_id = input("Please enter Bitwarden account API client ID: ")
|
||||
else:
|
||||
account_api_client_id = accounts[email]['account_api_client_id']
|
||||
|
||||
if ask_for_confirmation("Would you like to edit the Bitwarden account API secret?"):
|
||||
while True:
|
||||
account_api_secret = getpass.getpass("Please enter Bitwarden account API secret: ")
|
||||
account_api_secret2 = getpass.getpass("Please confirm Bitwarden account API secret: ")
|
||||
if account_api_secret == account_api_secret2:
|
||||
break
|
||||
else:
|
||||
print("The Bitwarden account API secrets do not match, please try again.")
|
||||
else:
|
||||
account_api_secret = accounts[email]['account_api_secret']
|
||||
|
||||
if ask_for_confirmation("Would you like to edit the Bitwarden account vault password?"):
|
||||
while True:
|
||||
account_vault_password = getpass.getpass("Please enter Bitwarden account vault password: ")
|
||||
account_vault_password2 = getpass.getpass("Please confirm Bitwarden account vault password: ")
|
||||
if account_vault_password == account_vault_password2:
|
||||
break
|
||||
else:
|
||||
print("The Bitwarden account vault passwords do not match, please try again.")
|
||||
else:
|
||||
account_vault_password = accounts[email]['account_vault_password']
|
||||
|
||||
array = dict()
|
||||
array[account_email_address] = dict()
|
||||
array[account_email_address]["account_api_client_id"] = account_api_client_id
|
||||
array[account_email_address]["account_api_secret"] = account_api_secret
|
||||
array[account_email_address]["account_vault_password"] = account_vault_password
|
||||
return array
|
||||
|
||||
def select_account(accounts, wording = "edit"):
|
||||
print("Which account would you like to {}:".format(wording))
|
||||
print(" ")
|
||||
emails = list(accounts)
|
||||
for i in range(0, len(accounts)):
|
||||
pretty_number = i + 1
|
||||
print("{}) {}".format(pretty_number, emails[i]))
|
||||
print(" ")
|
||||
while True:
|
||||
account_to_modify = int(input("Please enter number relating to the account you wish to {}: ".format(wording))) - 1
|
||||
try:
|
||||
return emails[account_to_modify]
|
||||
except IndexError as error:
|
||||
print("you entered a number out of range, please try again")
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
# Build and parse arguments
|
||||
parser = optparse.OptionParser(
|
||||
usage="%prog [options]",
|
||||
description="Run Bitwarden backup opteration. This will produce an encrypted zip/tar with exported CSV, JSON, and attachements.")
|
||||
|
||||
parser.add_option(
|
||||
"-c",
|
||||
"--config",
|
||||
action="store_true",
|
||||
dest="config",
|
||||
help="Edit Bitwarden account configuration."
|
||||
)
|
||||
parser.add_option (
|
||||
"-v",
|
||||
"--verbose",
|
||||
action="store_true",
|
||||
dest="debug",
|
||||
help="Output debug/verbose info to the console for troubleshooting."
|
||||
)
|
||||
parser.add_option (
|
||||
"--no-encryption",
|
||||
action="store_true",
|
||||
dest="no_encrypt",
|
||||
help="Will only zip up export and will NOT encrypt anything."
|
||||
)
|
||||
opts, args = parser.parse_args(sys.argv[1:])
|
||||
|
||||
os_detected = platform.system()
|
||||
script_directory = os.path.dirname(os.path.realpath(__file__))
|
||||
working_directory = os.path.join(script_directory, "working")
|
||||
exports_directory = os.path.join(script_directory, "exports")
|
||||
script_name = os.path.basename(__file__)
|
||||
secrets_config_file = os.path.join(script_directory, "secrets.config")
|
||||
pykmip_client_config_file = os.path.join(script_directory, "conf", "client.conf")
|
||||
log_file = os.path.join(script_directory, "log.log")
|
||||
datetime_string = datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
|
||||
|
||||
if opts.debug:
|
||||
logger = build_logger(logging.DEBUG)
|
||||
else:
|
||||
logger = build_logger(logging.INFO)
|
||||
|
||||
if os_detected == "Windows":
|
||||
bitwarden_cli_executable = os.path.join(script_directory, "lib", "Bitwarden CLI", "bw.exe")
|
||||
gpg_executable = os.path.join(script_directory, "lib", "gpg", "bin", "gpg.exe")
|
||||
sdelete_executable = os.path.join(script_directory, "lib", "sdelete.exe")
|
||||
elif os_detected == "Linux":
|
||||
bitwarden_cli_executable = os.path.join(script_directory, "lib", "Bitwarden CLI", "bw_linux")
|
||||
gpg_executable = "gpg"
|
||||
#elif os_detected == "macOS":
|
||||
# bitwarden_cli_executable = os.path.join(script_directory, "lib", "Bitwarden CLI", "bw_macOS")
|
||||
else:
|
||||
print("Your OS is not supported. Only Windows, Linux, and macOS are supported. Those are the only three supported OSes for the Bitwarden CLI.")
|
||||
print("Detected OS: {0}".format(os_detected))
|
||||
sys.exit(1)
|
||||
|
||||
client = client.ProxyKmipClient(config_file=pykmip_client_config_file)
|
||||
client.open()
|
||||
#print(encrypt(client, "test"))
|
||||
|
||||
|
||||
if opts.config:
|
||||
while True:
|
||||
if not os.path.exists(secrets_config_file):
|
||||
print("No Bitwarden accounts found, do you want to make a new one?")
|
||||
print(" ")
|
||||
print("n) New account")
|
||||
print("q) Quit config")
|
||||
while True:
|
||||
user_input = input("n/q> ")
|
||||
if user_input.casefold() == "n":
|
||||
account_details = new_account_details()
|
||||
write_config_file(account_details, secrets_config_file)
|
||||
break
|
||||
elif user_input.casefold() == "q":
|
||||
sys.exit(0)
|
||||
else:
|
||||
print("This value must be one of the following characters: n, q.")
|
||||
accounts = read_config_file(secrets_config_file)
|
||||
print("Current Bitwarden accounts:")
|
||||
print(" ")
|
||||
for account in accounts:
|
||||
print(account)
|
||||
print(" ")
|
||||
print("e) Edit account")
|
||||
print("n) New account")
|
||||
print("d) Delete account")
|
||||
print("q) Quit config")
|
||||
while True:
|
||||
user_input = input("e/n/d/q> ")
|
||||
# Editing an account
|
||||
if user_input.casefold() == "e":
|
||||
account_to_edit = select_account(accounts)
|
||||
account_details = edit_account_details(accounts, account_to_edit)
|
||||
del accounts[account_to_edit]
|
||||
accounts.update(account_details)
|
||||
write_config_file(accounts, secrets_config_file)
|
||||
break
|
||||
# Createing a new account
|
||||
elif user_input.casefold() == "n":
|
||||
account_details = new_account_details()
|
||||
accounts.update(account_details)
|
||||
write_config_file(accounts, secrets_config_file)
|
||||
break
|
||||
|
||||
# Deleting an account
|
||||
elif user_input.casefold() == "d":
|
||||
account_to_delete = select_account(accounts, "delete")
|
||||
if not ask_for_confirmation("Are you sure you wish to delete {} account? ".format(account_to_delete)):
|
||||
break
|
||||
del accounts[account_to_delete]
|
||||
if len(accounts) == 0:
|
||||
# no more accounts, remove secrets file
|
||||
os.remove(secrets_config_file)
|
||||
else:
|
||||
write_config_file(accounts, secrets_config_file)
|
||||
break
|
||||
|
||||
# Quit the config
|
||||
elif user_input.casefold() == "q":
|
||||
sys.exit(0)
|
||||
|
||||
# Catch all for non-valid characters
|
||||
else:
|
||||
print("This value must be one of the following characters: e, n, d, q.")
|
||||
|
||||
#json.loads((subprocess.check_output(['bw.exe','status'])).decode())['status']
|
||||
if not os.path.exists(secrets_config_file):
|
||||
print("No configuration file found. Please run {} -c to configure your accounts.".format(script_name))
|
||||
sys.exit(-1)
|
||||
accounts = read_config_file(secrets_config_file)
|
||||
emails = list(accounts)
|
||||
for email in emails:
|
||||
vault_password = accounts[email]['account_vault_password']
|
||||
os.environ["BW_CLIENTID"] = accounts[email]['account_api_client_id']
|
||||
os.environ["BW_CLIENTSECRET"] = accounts[email]['account_api_secret']
|
||||
|
||||
# login to Bitwarden
|
||||
logger.info("Trying to login to Bitwarden as {}".format(email))
|
||||
bitwarden_login_output = subprocess.run([bitwarden_cli_executable, 'login', '--apikey', '--raw'], capture_output=True)
|
||||
logger.debug((bitwarden_login_output.stdout).decode())
|
||||
bitwarden_status = json.loads(((subprocess.run([bitwarden_cli_executable, 'status'], capture_output=True)).stdout).decode())
|
||||
logger.debug("Bitwarden Status: {}".format(bitwarden_status))
|
||||
if bitwarden_status['status'] == "locked":
|
||||
logger.info("Successfully Logged in")
|
||||
bitwarden_unlock_output = subprocess.run([bitwarden_cli_executable, 'unlock', vault_password, '--raw', '--nointeraction'], capture_output=True)
|
||||
bitwarden_session_key = (bitwarden_unlock_output.stdout).decode()
|
||||
if bitwarden_session_key:
|
||||
# logger.debug("Session key: {}".format(bitwarden_session_key))
|
||||
logger.info("Successfully unlocked vault")
|
||||
os.environ["BW_SESSION"] = bitwarden_session_key
|
||||
|
||||
# export to csv and json
|
||||
logger.info("Exporting vault to both CSV and JSON files")
|
||||
logger.debug("Exporting vault to CSV")
|
||||
file_name = 'Bitwarden {} Export {}'.format(email, datetime_string)
|
||||
while True:
|
||||
logger.debug((subprocess.run([bitwarden_cli_executable, 'export', '--output', os.path.join(working_directory, '{}.csv'.format(file_name)) , '--format', 'csv'], capture_output=True).stdout).decode())
|
||||
time.sleep(1)
|
||||
file_size = os.path.getsize(os.path.join(working_directory, '{}.csv'.format(file_name)))
|
||||
if (file_size > 0):
|
||||
break
|
||||
else:
|
||||
logger.info("CSV export did not run correctly, running export again")
|
||||
if os.path.exists(os.path.join(working_directory, '{}.csv'.format(file_name))):
|
||||
os.remove(os.path.join(working_directory, '{}.csv'.format(file_name)))
|
||||
time.sleep(5)
|
||||
logger.debug("Exporting vault to JSON")
|
||||
while True:
|
||||
logger.debug((subprocess.run([bitwarden_cli_executable, 'export', '--output', os.path.join(working_directory, '{}.json'.format(file_name)), '--format', 'json'], capture_output=True).stdout).decode())
|
||||
time.sleep(1)
|
||||
file_size = os.path.getsize(os.path.join(working_directory, '{}.json'.format(file_name)))
|
||||
if (file_size > 56):
|
||||
break
|
||||
else:
|
||||
logger.info("JSON export did not run correctly, running export again")
|
||||
if os.path.exists(os.path.join(working_directory, '{}.json'.format(file_name))):
|
||||
os.remove(os.path.join(working_directory, '{}.json'.format(file_name)))
|
||||
time.sleep(5)
|
||||
|
||||
# looking for Organizations
|
||||
# look for organizations
|
||||
logger.info("Looking for Organizations")
|
||||
bitwarden_organizations = json.loads(((subprocess.run([bitwarden_cli_executable, 'list', 'organizations'], capture_output=True)).stdout).decode())
|
||||
|
||||
logger.info("Found {} Organiztaions.".format(len(bitwarden_organizations)))
|
||||
|
||||
for organization in bitwarden_organizations:
|
||||
logger.info("Exporting organization {} vault to both CSV and JSON files".format(organization['name']))
|
||||
logger.debug("Exporting organization vault to CSV")
|
||||
file_name = 'Bitwarden Organization {} Export {}'.format(organization['name'], datetime_string)
|
||||
while True:
|
||||
logger.debug((subprocess.run([bitwarden_cli_executable, 'export', '--organizationid', '{}'.format(organization['id']), '--output', os.path.join(working_directory, '{}.csv'.format(file_name)), '--format', 'csv'], capture_output=True).stdout).decode())
|
||||
time.sleep(1)
|
||||
file_size = os.path.getsize(os.path.join(working_directory, '{}.csv'.format(file_name)))
|
||||
if (file_size > 0):
|
||||
break
|
||||
else:
|
||||
logger.info("CSV export did not run correctly, running export again")
|
||||
time.sleep(5)
|
||||
logger.debug("Exporting organization vault to JSON")
|
||||
while True:
|
||||
logger.debug((subprocess.run([bitwarden_cli_executable, 'export', '--organizationid', '{}'.format(organization['id']), '--output', os.path.join(working_directory, '{}.json'.format(file_name)), '--format', 'json'], capture_output=True).stdout).decode())
|
||||
time.sleep(1)
|
||||
file_size = os.path.getsize(os.path.join(working_directory, '{}.json'.format(file_name)))
|
||||
if (file_size > 56):
|
||||
break
|
||||
else:
|
||||
logger.info("JSON export did not run correctly, running export again")
|
||||
time.sleep(5)
|
||||
|
||||
logger.info("Downlading attachments...")
|
||||
bitwarden_items = json.loads(((subprocess.run([bitwarden_cli_executable, 'list', 'items'], capture_output=True)).stdout).decode())
|
||||
for item in bitwarden_items:
|
||||
logger.debug("Working on item {} ({})".format(item['name'], item['id']))
|
||||
if "attachments" in item:
|
||||
logger.debug("Found {} attachments".format(len(item['attachments'])))
|
||||
attachment_folder_name = os.path.join(working_directory, "attachments", item['name'])
|
||||
for attachment in item['attachments']:
|
||||
logger.debug("Downloading attachment ({}) with name {} to folder {}".format(attachment['id'], attachment['fileName'], attachment_folder_name))
|
||||
logger.info((subprocess.run([bitwarden_cli_executable, 'get', 'attachment', attachment['id'], '--itemid', item['id'], '--output', os.path.join(attachment_folder_name, attachment['fileName'])], capture_output=True).stdout).decode())
|
||||
time.sleep(1)
|
||||
else:
|
||||
logger.debug("Item has no attachments")
|
||||
logger.info("Done downloading attachments")
|
||||
|
||||
logger.info("Zipping everything together...")
|
||||
zip_filename = os.path.join(exports_directory, "Bitwarden Backup {} {}".format(email, datetime_string))
|
||||
shutil.make_archive(zip_filename, format="zip", root_dir=working_directory)
|
||||
|
||||
if not opts.no_encrypt:
|
||||
logger.debug((subprocess.run([gpg_executable, '--no-options', '--batch', '--passphrase', vault_password, '--symmetric', '--cipher-algo', 'AES256', '--digest-algo', 'SHA512', '--compression-algo', 'Uncompressed', '--output', zip_filename + '.zip.gpg', zip_filename + '.zip'], capture_output=True).stdout).decode())
|
||||
|
||||
logger.info("Securely deleting files")
|
||||
if os_detected == "Windows":
|
||||
# sdelete.exe .\working\ -p 5 -s
|
||||
logger.debug((subprocess.run([sdelete_executable, '-p', '5', '-s', working_directory], capture_output=True).stdout).decode())
|
||||
if not opts.no_encrypt:
|
||||
logger.debug((subprocess.run([sdelete_executable, '-p', '5', zip_filename + ".zip"], capture_output=True).stdout).decode())
|
||||
elif os_detected == "Linux":
|
||||
# find <directory> -depth -type f -exec shred -v -n 1 -z -u {} \;
|
||||
logger.debug((subprocess.run(['find', working_directory, '-depth', '-type', 'f', '-exec', 'shred', '-v', '-n', '5', '-u', '/{/}', '\/', ';'], capture_output=True).stdout).decode())
|
||||
if not opts.no_encrypt:
|
||||
logger.debug((subprocess.run(['shred', '-v', '-u', '-n', '5', zip_filename + '.zip'], capture_output=True).stdout).decode())
|
||||
|
||||
else:
|
||||
logger.error((bitwarden_unlock_output.stderr).decode())
|
||||
else:
|
||||
logger.error("Unable to login to account, please check API credentials")
|
||||
#logger.error((bitwarden_login_output.stderr).decode())
|
||||
|
||||
del vault_password
|
||||
del os.environ['BW_CLIENTID']
|
||||
del os.environ['BW_CLIENTSECRET']
|
||||
if "BW_SESSION" in os.environ:
|
||||
del os.environ["BW_SESSION"]
|
||||
logger.info("Logging out of your Bitwarden account")
|
||||
logger.debug((subprocess.run([bitwarden_cli_executable, 'logout'], capture_output=True).stdout).decode())
|
||||
|
||||
del accounts
|
||||
del emails
|
||||
client.close()
|
||||
sys.exit(0)
|
||||
11
conf/client.conf.sample
Normal file
11
conf/client.conf.sample
Normal file
@@ -0,0 +1,11 @@
|
||||
# THIS IS A SAMPLE FILE, PLEASE COPY IT AND EDIT THE COPY
|
||||
[client]
|
||||
host=127.0.0.1
|
||||
port=5696
|
||||
certfile=kmip.crt
|
||||
keyfile=kmip.key
|
||||
ca_certs=kmip.crt
|
||||
cert_reqs=CERT_REQUIRED
|
||||
ssl_version=PROTOCOL_TLS
|
||||
do_handshake_on_connect=True
|
||||
suppress_ragged_eofs=True
|
||||
BIN
lib/7-Zip/7za.dll
Normal file
BIN
lib/7-Zip/7za.dll
Normal file
Binary file not shown.
BIN
lib/7-Zip/7za.exe
Normal file
BIN
lib/7-Zip/7za.exe
Normal file
Binary file not shown.
BIN
lib/7-Zip/7zxa.dll
Normal file
BIN
lib/7-Zip/7zxa.dll
Normal file
Binary file not shown.
BIN
lib/7za.exe
BIN
lib/7za.exe
Binary file not shown.
BIN
lib/bw.exe
BIN
lib/bw.exe
Binary file not shown.
@@ -1,2 +1,2 @@
|
||||
gnupg
|
||||
2.2.28
|
||||
2.3.6
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,5 +1,6 @@
|
||||
/* gcrypt.h - GNU Cryptographic Library Interface -*- c -*-
|
||||
* Copyright (C) 2012-2021 g10 Code GmbH
|
||||
* Copyright (C) 2012-2022 g10 Code GmbH
|
||||
* Copyright (C) 2013-2022 Jussi Kivilinna
|
||||
* Copyright (C) 1998-2018 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of Libgcrypt.
|
||||
@@ -16,7 +17,6 @@
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*
|
||||
* File: src/gcrypt.h. Generated from gcrypt.h.in by configure.
|
||||
*/
|
||||
@@ -33,20 +33,11 @@
|
||||
#include <sys/types.h>
|
||||
|
||||
#if defined _WIN32 || defined __WIN32__
|
||||
# include <winsock2.h>
|
||||
# include <ws2tcpip.h>
|
||||
# include <time.h>
|
||||
# ifndef __GNUC__
|
||||
typedef long ssize_t;
|
||||
typedef int pid_t;
|
||||
# endif /*!__GNUC__*/
|
||||
#else
|
||||
# include <sys/socket.h>
|
||||
# include <sys/time.h>
|
||||
#
|
||||
#endif /*!_WIN32*/
|
||||
|
||||
typedef int gcry_socklen_t;
|
||||
#endif /*_WIN32*/
|
||||
|
||||
/* This is required for error code compatibility. */
|
||||
#define _GCRY_ERR_SOURCE_DEFAULT GPG_ERR_SOURCE_GCRYPT
|
||||
@@ -63,11 +54,11 @@ extern "C" {
|
||||
return the same version. The purpose of this macro is to let
|
||||
autoconf (using the AM_PATH_GCRYPT macro) check that this header
|
||||
matches the installed library. */
|
||||
#define GCRYPT_VERSION "1.8.8"
|
||||
#define GCRYPT_VERSION "1.10.1"
|
||||
|
||||
/* The version number of this header. It may be used to handle minor
|
||||
API incompatibilities. */
|
||||
#define GCRYPT_VERSION_NUMBER 0x010808
|
||||
#define GCRYPT_VERSION_NUMBER 0x010a01
|
||||
|
||||
|
||||
/* Internal: We can't use the convenience macros for the multi
|
||||
@@ -128,7 +119,7 @@ extern "C" {
|
||||
#ifdef _GCRYPT_IN_LIBGCRYPT
|
||||
#define _GCRY_ATTR_INTERNAL
|
||||
#else
|
||||
#define _GCRY_ATTR_INTERNAL _GCRY_GCC_ATTR_DEPRECATED
|
||||
#define _GCRY_ATTR_INTERNAL _GCRY_GCC_ATTR_DEPRECATED
|
||||
#endif
|
||||
|
||||
/* Wrappers for the libgpg-error library. */
|
||||
@@ -333,7 +324,13 @@ enum gcry_ctl_cmds
|
||||
GCRYCTL_DRBG_REINIT = 74,
|
||||
GCRYCTL_SET_TAGLEN = 75,
|
||||
GCRYCTL_GET_TAGLEN = 76,
|
||||
GCRYCTL_REINIT_SYSCALL_CLAMP = 77
|
||||
GCRYCTL_REINIT_SYSCALL_CLAMP = 77,
|
||||
GCRYCTL_AUTO_EXPAND_SECMEM = 78,
|
||||
GCRYCTL_SET_ALLOW_WEAK_KEY = 79,
|
||||
GCRYCTL_SET_DECRYPTION_TAG = 80,
|
||||
GCRYCTL_FIPS_SERVICE_INDICATOR_CIPHER = 81,
|
||||
GCRYCTL_FIPS_SERVICE_INDICATOR_KDF = 82,
|
||||
GCRYCTL_NO_FIPS_MODE = 83
|
||||
};
|
||||
|
||||
/* Perform various operations defined by CMD. */
|
||||
@@ -387,7 +384,7 @@ gcry_error_t gcry_sexp_build (gcry_sexp_t *retsexp, size_t *erroff,
|
||||
/* Like gcry_sexp_build, but uses an array instead of variable
|
||||
function arguments. */
|
||||
gcry_error_t gcry_sexp_build_array (gcry_sexp_t *retsexp, size_t *erroff,
|
||||
const char *format, void **arg_list);
|
||||
const char *format, void **arg_list);
|
||||
|
||||
/* Release the S-expression object SEXP */
|
||||
void gcry_sexp_release (gcry_sexp_t sexp);
|
||||
@@ -588,6 +585,9 @@ gcry_mpi_t gcry_mpi_set (gcry_mpi_t w, const gcry_mpi_t u);
|
||||
/* Store the unsigned integer value U in W. */
|
||||
gcry_mpi_t gcry_mpi_set_ui (gcry_mpi_t w, unsigned long u);
|
||||
|
||||
/* Store U as an unsigned int at W or return GPG_ERR_ERANGE. */
|
||||
gpg_error_t gcry_mpi_get_ui (unsigned int *w, gcry_mpi_t u);
|
||||
|
||||
/* Swap the values of A and B. */
|
||||
void gcry_mpi_swap (gcry_mpi_t a, gcry_mpi_t b);
|
||||
|
||||
@@ -841,6 +841,7 @@ gcry_mpi_t _gcry_mpi_get_const (int no);
|
||||
#define mpi_snatch( w, u) gcry_mpi_snatch( (w), (u) )
|
||||
#define mpi_set( w, u) gcry_mpi_set( (w), (u) )
|
||||
#define mpi_set_ui( w, u) gcry_mpi_set_ui( (w), (u) )
|
||||
#define mpi_get_ui( w, u) gcry_mpi_get_ui( (w), (u) )
|
||||
#define mpi_abs( w ) gcry_mpi_abs( (w) )
|
||||
#define mpi_neg( w, u) gcry_mpi_neg( (w), (u) )
|
||||
#define mpi_cmp( u, v ) gcry_mpi_cmp( (u), (v) )
|
||||
@@ -940,7 +941,9 @@ enum gcry_cipher_algos
|
||||
GCRY_CIPHER_SALSA20 = 313,
|
||||
GCRY_CIPHER_SALSA20R12 = 314,
|
||||
GCRY_CIPHER_GOST28147 = 315,
|
||||
GCRY_CIPHER_CHACHA20 = 316
|
||||
GCRY_CIPHER_CHACHA20 = 316,
|
||||
GCRY_CIPHER_GOST28147_MESH = 317, /* With CryptoPro key meshing. */
|
||||
GCRY_CIPHER_SM4 = 318
|
||||
};
|
||||
|
||||
/* The Rijndael algorithm is basically AES, so provide some macros. */
|
||||
@@ -967,7 +970,10 @@ enum gcry_cipher_modes
|
||||
GCRY_CIPHER_MODE_POLY1305 = 10, /* Poly1305 based AEAD mode. */
|
||||
GCRY_CIPHER_MODE_OCB = 11, /* OCB3 mode. */
|
||||
GCRY_CIPHER_MODE_CFB8 = 12, /* Cipher feedback (8 bit mode). */
|
||||
GCRY_CIPHER_MODE_XTS = 13 /* XTS mode. */
|
||||
GCRY_CIPHER_MODE_XTS = 13, /* XTS mode. */
|
||||
GCRY_CIPHER_MODE_EAX = 14, /* EAX mode. */
|
||||
GCRY_CIPHER_MODE_SIV = 15, /* SIV mode. */
|
||||
GCRY_CIPHER_MODE_GCM_SIV = 16 /* GCM-SIV mode. */
|
||||
};
|
||||
|
||||
/* Flags used with the open function. */
|
||||
@@ -976,7 +982,8 @@ enum gcry_cipher_flags
|
||||
GCRY_CIPHER_SECURE = 1, /* Allocate in secure memory. */
|
||||
GCRY_CIPHER_ENABLE_SYNC = 2, /* Enable CFB sync mode. */
|
||||
GCRY_CIPHER_CBC_CTS = 4, /* Enable CBC cipher text stealing (CTS). */
|
||||
GCRY_CIPHER_CBC_MAC = 8 /* Enable CBC message auth. code (MAC). */
|
||||
GCRY_CIPHER_CBC_MAC = 8, /* Enable CBC message auth. code (MAC). */
|
||||
GCRY_CIPHER_EXTENDED = 16 /* Enable extended AES-WRAP. */
|
||||
};
|
||||
|
||||
/* GCM works only with blocks of 128 bits */
|
||||
@@ -991,6 +998,9 @@ enum gcry_cipher_flags
|
||||
/* XTS works only with blocks of 128 bits. */
|
||||
#define GCRY_XTS_BLOCK_LEN (128 / 8)
|
||||
|
||||
/* SIV and GCM-SIV works only with blocks of 128 bits */
|
||||
#define GCRY_SIV_BLOCK_LEN (128 / 8)
|
||||
|
||||
/* Create a handle for algorithm ALGO to be used in MODE. FLAGS may
|
||||
be given as an bitwise OR of the gcry_cipher_flags values. */
|
||||
gcry_error_t gcry_cipher_open (gcry_cipher_hd_t *handle,
|
||||
@@ -1093,6 +1103,11 @@ size_t gcry_cipher_get_algo_blklen (int algo);
|
||||
#define gcry_cipher_test_algo(a) \
|
||||
gcry_cipher_algo_info( (a), GCRYCTL_TEST_ALGO, NULL, NULL )
|
||||
|
||||
/* Setup tag for decryption (for SIV and GCM-SIV mode). */
|
||||
#define gcry_cipher_set_decryption_tag(a, tag, taglen) \
|
||||
gcry_cipher_ctl ((a), GCRYCTL_SET_DECRYPTION_TAG, \
|
||||
(void *)(tag), (taglen))
|
||||
|
||||
|
||||
/************************************
|
||||
* *
|
||||
@@ -1192,6 +1207,28 @@ gcry_sexp_t gcry_pk_get_param (int algo, const char *name);
|
||||
/* Return an S-expression representing the context CTX. */
|
||||
gcry_error_t gcry_pubkey_get_sexp (gcry_sexp_t *r_sexp,
|
||||
int mode, gcry_ctx_t ctx);
|
||||
|
||||
/************************************
|
||||
* *
|
||||
* Modern ECC Functions *
|
||||
* *
|
||||
************************************/
|
||||
|
||||
/* The curves we support. */
|
||||
enum gcry_ecc_curves
|
||||
{
|
||||
GCRY_ECC_CURVE25519 = 1,
|
||||
GCRY_ECC_CURVE448 = 2
|
||||
};
|
||||
|
||||
/* Get the length of point to prepare buffer for the result. */
|
||||
unsigned int gcry_ecc_get_algo_keylen (int curveid);
|
||||
|
||||
/* Convenience function to compute scalar multiplication of the
|
||||
* Montgomery form of curve. */
|
||||
gpg_error_t gcry_ecc_mul_point (int curveid, unsigned char *result,
|
||||
const unsigned char *scalar,
|
||||
const unsigned char *point);
|
||||
|
||||
|
||||
|
||||
@@ -1241,7 +1278,10 @@ enum gcry_md_algos
|
||||
GCRY_MD_BLAKE2S_256 = 322,
|
||||
GCRY_MD_BLAKE2S_224 = 323,
|
||||
GCRY_MD_BLAKE2S_160 = 324,
|
||||
GCRY_MD_BLAKE2S_128 = 325
|
||||
GCRY_MD_BLAKE2S_128 = 325,
|
||||
GCRY_MD_SM3 = 326,
|
||||
GCRY_MD_SHA512_256 = 327,
|
||||
GCRY_MD_SHA512_224 = 328
|
||||
};
|
||||
|
||||
/* Flags used with the open function. */
|
||||
@@ -1408,6 +1448,7 @@ typedef struct gcry_mac_handle *gcry_mac_hd_t;
|
||||
enum gcry_mac_algos
|
||||
{
|
||||
GCRY_MAC_NONE = 0,
|
||||
GCRY_MAC_GOST28147_IMIT = 1,
|
||||
|
||||
GCRY_MAC_HMAC_SHA256 = 101,
|
||||
GCRY_MAC_HMAC_SHA224 = 102,
|
||||
@@ -1427,6 +1468,18 @@ enum gcry_mac_algos
|
||||
GCRY_MAC_HMAC_SHA3_256 = 116,
|
||||
GCRY_MAC_HMAC_SHA3_384 = 117,
|
||||
GCRY_MAC_HMAC_SHA3_512 = 118,
|
||||
GCRY_MAC_HMAC_GOSTR3411_CP = 119,
|
||||
GCRY_MAC_HMAC_BLAKE2B_512 = 120,
|
||||
GCRY_MAC_HMAC_BLAKE2B_384 = 121,
|
||||
GCRY_MAC_HMAC_BLAKE2B_256 = 122,
|
||||
GCRY_MAC_HMAC_BLAKE2B_160 = 123,
|
||||
GCRY_MAC_HMAC_BLAKE2S_256 = 124,
|
||||
GCRY_MAC_HMAC_BLAKE2S_224 = 125,
|
||||
GCRY_MAC_HMAC_BLAKE2S_160 = 126,
|
||||
GCRY_MAC_HMAC_BLAKE2S_128 = 127,
|
||||
GCRY_MAC_HMAC_SM3 = 128,
|
||||
GCRY_MAC_HMAC_SHA512_256 = 129,
|
||||
GCRY_MAC_HMAC_SHA512_224 = 130,
|
||||
|
||||
GCRY_MAC_CMAC_AES = 201,
|
||||
GCRY_MAC_CMAC_3DES = 202,
|
||||
@@ -1439,6 +1492,7 @@ enum gcry_mac_algos
|
||||
GCRY_MAC_CMAC_RFC2268 = 209,
|
||||
GCRY_MAC_CMAC_IDEA = 210,
|
||||
GCRY_MAC_CMAC_GOST28147 = 211,
|
||||
GCRY_MAC_CMAC_SM4 = 212,
|
||||
|
||||
GCRY_MAC_GMAC_AES = 401,
|
||||
GCRY_MAC_GMAC_CAMELLIA = 402,
|
||||
@@ -1538,7 +1592,16 @@ enum gcry_kdf_algos
|
||||
GCRY_KDF_ITERSALTED_S2K = 19,
|
||||
GCRY_KDF_PBKDF1 = 33,
|
||||
GCRY_KDF_PBKDF2 = 34,
|
||||
GCRY_KDF_SCRYPT = 48
|
||||
GCRY_KDF_SCRYPT = 48,
|
||||
GCRY_KDF_ARGON2 = 64,
|
||||
GCRY_KDF_BALLOON = 65
|
||||
};
|
||||
|
||||
enum gcry_kdf_subalgo_argon2
|
||||
{
|
||||
GCRY_KDF_ARGON2D = 0,
|
||||
GCRY_KDF_ARGON2I = 1,
|
||||
GCRY_KDF_ARGON2ID = 2
|
||||
};
|
||||
|
||||
/* Derive a key from a passphrase. */
|
||||
@@ -1548,8 +1611,33 @@ gpg_error_t gcry_kdf_derive (const void *passphrase, size_t passphraselen,
|
||||
unsigned long iterations,
|
||||
size_t keysize, void *keybuffer);
|
||||
|
||||
/* Another API to derive a key from a passphrase. */
|
||||
typedef struct gcry_kdf_handle *gcry_kdf_hd_t;
|
||||
|
||||
typedef void (*gcry_kdf_job_fn_t) (void *priv);
|
||||
typedef int (*gcry_kdf_dispatch_job_fn_t) (void *jobs_context,
|
||||
gcry_kdf_job_fn_t job_fn,
|
||||
void *job_priv);
|
||||
typedef int (*gcry_kdf_wait_all_jobs_fn_t) (void *jobs_context);
|
||||
|
||||
/* Exposed structure for KDF computation to decouple thread functionality. */
|
||||
typedef struct gcry_kdf_thread_ops
|
||||
{
|
||||
void *jobs_context;
|
||||
gcry_kdf_dispatch_job_fn_t dispatch_job;
|
||||
gcry_kdf_wait_all_jobs_fn_t wait_all_jobs;
|
||||
} gcry_kdf_thread_ops_t;
|
||||
|
||||
gcry_error_t gcry_kdf_open (gcry_kdf_hd_t *hd, int algo, int subalgo,
|
||||
const unsigned long *param, unsigned int paramlen,
|
||||
const void *passphrase, size_t passphraselen,
|
||||
const void *salt, size_t saltlen,
|
||||
const void *key, size_t keylen,
|
||||
const void *ad, size_t adlen);
|
||||
gcry_error_t gcry_kdf_compute (gcry_kdf_hd_t h,
|
||||
const gcry_kdf_thread_ops_t *ops);
|
||||
gcry_error_t gcry_kdf_final (gcry_kdf_hd_t h, size_t resultlen, void *result);
|
||||
void gcry_kdf_close (gcry_kdf_hd_t h);
|
||||
|
||||
/************************************
|
||||
* *
|
||||
@@ -1600,8 +1688,7 @@ void *gcry_random_bytes (size_t nbytes, enum gcry_random_level level)
|
||||
_GCRY_GCC_ATTR_MALLOC;
|
||||
|
||||
/* Return NBYTES of allocated random using a random numbers of quality
|
||||
LEVEL. The random numbers are created returned in "secure"
|
||||
memory. */
|
||||
LEVEL. The random is returned in "secure" memory. */
|
||||
void *gcry_random_bytes_secure (size_t nbytes, enum gcry_random_level level)
|
||||
_GCRY_GCC_ATTR_MALLOC;
|
||||
|
||||
@@ -1784,6 +1871,32 @@ int gcry_is_secure (const void *a) _GCRY_GCC_ATTR_PURE;
|
||||
/* Return true if Libgcrypt is in FIPS mode. */
|
||||
#define gcry_fips_mode_active() !!gcry_control (GCRYCTL_FIPS_MODE_P, 0)
|
||||
|
||||
/* Variant of gcry_pk_sign which takes as additional parameter a HD
|
||||
* handle for hash and an optional context. The hash algorithm used by the
|
||||
* handle needs to be enabled and input needs to be supplied beforehand.
|
||||
* DATA-TMPL specifies a template to compose an S-expression to be signed.
|
||||
* A template should include '(hash %s %b)' or '(hash ALGONAME %b)'.
|
||||
* For the former case, '%s' is substituted by the string of algorithm
|
||||
* of gcry_md_get_algo (HD) and when gcry_md_read is called, ALGO=0 is
|
||||
* used internally. For the latter case, hash algorithm by ALGONAME
|
||||
* is used when gcry_md_read is called internally.
|
||||
* The hash handle must not yet been finalized; the function
|
||||
* takes a copy of the state and does a finalize on the copy. This
|
||||
* function shall be used if a policy requires that hashing and signing
|
||||
* is done by the same function. CTX is currently not used and should
|
||||
* be passed as NULL. */
|
||||
gcry_error_t gcry_pk_hash_sign (gcry_sexp_t *result,
|
||||
const char *data_tmpl, gcry_sexp_t skey,
|
||||
gcry_md_hd_t hd, gcry_ctx_t ctx);
|
||||
|
||||
/* Variant of gcry_pk_verify which takes as additional parameter a HD
|
||||
* handle for hash and an optional context. Similar to gcry_pk_hash_sign. */
|
||||
gcry_error_t gcry_pk_hash_verify (gcry_sexp_t sigval,
|
||||
const char *data_tmpl, gcry_sexp_t pkey,
|
||||
gcry_md_hd_t hd, gcry_ctx_t ctx);
|
||||
|
||||
gcry_error_t gcry_pk_random_override_new (gcry_ctx_t *r_ctx,
|
||||
const unsigned char *p, size_t len);
|
||||
|
||||
#if 0 /* (Keep Emacsens' auto-indent happy.) */
|
||||
{
|
||||
|
||||
@@ -66,12 +66,12 @@
|
||||
#include <stdarg.h>
|
||||
|
||||
/* The version string of this header. */
|
||||
#define GPG_ERROR_VERSION "1.42"
|
||||
#define GPGRT_VERSION "1.42"
|
||||
#define GPG_ERROR_VERSION "1.45"
|
||||
#define GPGRT_VERSION "1.45"
|
||||
|
||||
/* The version number of this header. */
|
||||
#define GPG_ERROR_VERSION_NUMBER 0x012a00
|
||||
#define GPGRT_VERSION_NUMBER 0x012a00
|
||||
#define GPG_ERROR_VERSION_NUMBER 0x012d00
|
||||
#define GPGRT_VERSION_NUMBER 0x012d00
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
@@ -1103,6 +1103,22 @@ size_t gpgrt_w32_iconv (gpgrt_w32_iconv_t cd,
|
||||
# define iconv(a,b,c,d,e) gpgrt_w32_iconv ((a),(b),(c),(d),(e))
|
||||
#endif /*GPGRT_ENABLE_W32_ICONV_MACROS*/
|
||||
|
||||
/* Release a wchar_t * buffer. */
|
||||
void gpgrt_free_wchar (wchar_t *wstring);
|
||||
|
||||
/* Convert an UTF-8 encoded file name to wchar.
|
||||
* Prepend a '\\?\' prefix if needed. */
|
||||
wchar_t *gpgrt_fname_to_wchar (const char *fname);
|
||||
|
||||
/* Convert an UTF8 string to a WCHAR string. Caller should use
|
||||
* gpgrt_free_wchar to release the result.
|
||||
* Returns NULL on error and sets ERRNO. */
|
||||
wchar_t *gpgrt_utf8_to_wchar (const char *string);
|
||||
|
||||
/* Convert a WCHAR string to UTF-8. Caller should use gpgrt_free to
|
||||
* release the result. Returns NULL on error and sets ERRNO. */
|
||||
char *gpgrt_wchar_to_utf8 (const wchar_t *wstring);
|
||||
|
||||
/* Query a string in the registry. */
|
||||
char *gpgrt_w32_reg_query_string (const char *root,
|
||||
const char *dir,
|
||||
@@ -1889,7 +1905,8 @@ typedef struct
|
||||
#define ARGPARSE_FLAG_USER 2048 /* Use user config file. */
|
||||
#define ARGPARSE_FLAG_VERBOSE 4096 /* Print additional argparser info. */
|
||||
#define ARGPARSE_FLAG_USERVERS 8192 /* Try version-ed user config files. */
|
||||
#define ARGPARSE_FLAG_WITHATTR 16384 /* Return attribute bits. */
|
||||
#define ARGPARSE_FLAG_WITHATTR 16384 /* Return attribute bits. (Make sure */
|
||||
/* to act upon ARGPARSE_OPT_IGNORE.) */
|
||||
|
||||
/* Constants for (gpgrt_argparse_t).err. */
|
||||
#define ARGPARSE_PRINT_WARNING 1 /* Print a diagnostic. */
|
||||
|
||||
@@ -42,11 +42,11 @@ extern "C" {
|
||||
* instead. The purpose of this macro is to let autoconf (using the
|
||||
* AM_PATH_GPGME macro) check that this header matches the installed
|
||||
* library. */
|
||||
#define GPGME_VERSION "1.15.1"
|
||||
#define GPGME_VERSION "1.17.1"
|
||||
|
||||
/* The version number of this header. It may be used to handle minor
|
||||
* API incompatibilities. */
|
||||
#define GPGME_VERSION_NUMBER 0x010f01
|
||||
#define GPGME_VERSION_NUMBER 0x011101
|
||||
|
||||
|
||||
/* System specific typedefs. */
|
||||
@@ -414,8 +414,8 @@ gpgme_pinentry_mode_t;
|
||||
#define GPGME_EXPORT_MODE_SECRET 16
|
||||
#define GPGME_EXPORT_MODE_RAW 32
|
||||
#define GPGME_EXPORT_MODE_PKCS12 64
|
||||
#define GPGME_EXPORT_MODE_NOUID 128 /* Experimental(!)*/
|
||||
#define GPGME_EXPORT_MODE_SSH 256
|
||||
#define GPGME_EXPORT_MODE_SECRET_SUBKEY 512
|
||||
|
||||
typedef unsigned int gpgme_export_mode_t;
|
||||
|
||||
@@ -636,7 +636,13 @@ struct _gpgme_key_sig
|
||||
unsigned int exportable : 1;
|
||||
|
||||
/* Internal to GPGME, do not use. */
|
||||
unsigned int _unused : 28;
|
||||
unsigned int _unused : 12;
|
||||
|
||||
/* The depth of a trust signature, 0 if no trust signature. */
|
||||
unsigned int trust_depth : 8;
|
||||
|
||||
/* The trust value of a trust signature, 0 if no trust signature. */
|
||||
unsigned int trust_value : 8;
|
||||
|
||||
/* The public key algorithm used to create the signature. */
|
||||
gpgme_pubkey_algo_t pubkey_algo;
|
||||
@@ -683,6 +689,9 @@ struct _gpgme_key_sig
|
||||
|
||||
/* Internal to GPGME, do not use. */
|
||||
gpgme_sig_notation_t _last_notation;
|
||||
|
||||
/* The scope of a trust signature. Might be NULL. */
|
||||
char *trust_scope;
|
||||
};
|
||||
typedef struct _gpgme_key_sig *gpgme_key_sig_t;
|
||||
|
||||
@@ -1737,6 +1746,12 @@ gpgme_error_t gpgme_op_import (gpgme_ctx_t ctx, gpgme_data_t keydata);
|
||||
gpgme_error_t gpgme_op_import_keys_start (gpgme_ctx_t ctx, gpgme_key_t keys[]);
|
||||
gpgme_error_t gpgme_op_import_keys (gpgme_ctx_t ctx, gpgme_key_t keys[]);
|
||||
|
||||
/* Import the keys given by the array KEYIDS from a keyserver into the
|
||||
* keyring. */
|
||||
gpgme_error_t gpgme_op_receive_keys_start (gpgme_ctx_t ctx,
|
||||
const char *keyids[]);
|
||||
gpgme_error_t gpgme_op_receive_keys (gpgme_ctx_t ctx, const char *keyids[]);
|
||||
|
||||
|
||||
/* Export the keys found by PATTERN into KEYDATA. */
|
||||
gpgme_error_t gpgme_op_export_start (gpgme_ctx_t ctx, const char *pattern,
|
||||
@@ -1914,6 +1929,7 @@ gpgme_error_t gpgme_op_delete_ext (gpgme_ctx_t ctx, const gpgme_key_t key,
|
||||
#define GPGME_KEYSIGN_LOCAL (1 << 7) /* Create a local signature. */
|
||||
#define GPGME_KEYSIGN_LFSEP (1 << 8) /* Indicate LF separated user ids. */
|
||||
#define GPGME_KEYSIGN_NOEXPIRE (1 << 9) /* Force no expiration. */
|
||||
#define GPGME_KEYSIGN_FORCE (1 << 10) /* Force creation. */
|
||||
|
||||
|
||||
/* Sign the USERID of KEY using the current set of signers. */
|
||||
@@ -2471,6 +2487,11 @@ char *gpgme_addrspec_from_uid (const char *uid);
|
||||
* Deprecated types, constants and functions.
|
||||
*/
|
||||
|
||||
/* This is a former experimental only features. The constant is
|
||||
* provided to not break existing code in the compiler phase. */
|
||||
#define GPGME_EXPORT_MODE_NOUID 128 /* Do not use! */
|
||||
|
||||
|
||||
/* The possible stati for gpgme_op_edit. The use of that function and
|
||||
* these status codes are deprecated in favor of gpgme_op_interact. */
|
||||
typedef enum
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
2
requirements.txt
Normal file
2
requirements.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
pykmip
|
||||
secure_delete
|
||||
Reference in New Issue
Block a user