[med-svn] [Git][med-team/libsecrecy][upstream] New upstream version 0.0.5+ds
Étienne Mollier (@emollier)
gitlab at salsa.debian.org
Sat Oct 23 22:57:21 BST 2021
Étienne Mollier pushed to branch upstream at Debian Med / libsecrecy
Commits:
d9b3411b by Étienne Mollier at 2021-10-23T23:40:04+02:00
New upstream version 0.0.5+ds
- - - - -
12 changed files:
- ChangeLog
- configure.ac
- release.sh
- src/Makefile.am
- + src/apps/secrecy.1
- src/apps/secrecy.cpp
- src/libsecrecy/AESEncryptKey.hpp
- src/libsecrecy/GCMFactoryBase.hpp
- src/libsecrecy/GCMStreamHeader.hpp
- src/libsecrecy/RawKey.hpp
- + src/libsecrecy/SecrecyKeyValueStore.hpp
- − src/libsecrecy/libsecrecy.hpp
Changes:
=====================================
ChangeLog
=====================================
@@ -1,3 +1,24 @@
+libsecrecy (0.0.5-1) unstable; urgency=medium
+
+ * Update email address of Étienne Mollier in the manual page for secrecy
+ * Add manual page for secrecy app kindly provided by Étienne Mollier.
+
+ -- German Tischler-Höhle <germant at miltenyibiotec.de> Tue, 14 Sep 2021 09:29:12 +0200
+
+libsecrecy (0.0.4-1) unstable; urgency=medium
+
+ * Avoid object copying in SecrecyKeyValueStore during map traversal
+
+ -- German Tischler-Höhle <germant at miltenyibiotec.de> Mon, 13 Sep 2021 13:01:43 +0200
+
+libsecrecy (0.0.3-1) unstable; urgency=medium
+
+ * Remove autogenerated file
+ * Avoid object copying in GCMStreamHeader
+ * Check for existence of key directory when listing keys (output empty list instead of failing with an exception)
+
+ -- German Tischler-Höhle <germant at miltenyibiotec.de> Mon, 13 Sep 2021 12:34:49 +0200
+
libsecrecy (0.0.2-1) unstable; urgency=medium
* Implement key caching infrastructure
=====================================
configure.ac
=====================================
@@ -1,5 +1,5 @@
-AC_INIT(libsecrecy,0.0.2,[germant at miltenyibiotec.de],[libsecrecy],[https://gitlab.com/german.tischler/libsecrecy])
-LIBRARY_VERSION=0:2:0
+AC_INIT(libsecrecy,0.0.5,[germant at miltenyibiotec.de],[libsecrecy],[https://gitlab.com/german.tischler/libsecrecy])
+LIBRARY_VERSION=0:5:0
AC_MSG_NOTICE([Configuring for source in directory ${srcdir}])
AC_CANONICAL_SYSTEM
AC_CANONICAL_HOST
=====================================
release.sh
=====================================
@@ -1,4 +1,5 @@
#! /bin/bash
+set -e
# update branches
git checkout experimental
=====================================
src/Makefile.am
=====================================
@@ -11,6 +11,10 @@ lib_LTLIBRARIES = # libsecrecy.la
noinst_HEADERS = #
+MANPAGES = apps/secrecy.1
+man_MANS = ${MANPAGES}
+EXTRA_DIST = ${MANPAGES}
+
#libsecrecy_la_CPPFLAGS = ${AM_CPPFLAGS} @LIBSECRECYCPPFLAGS@ @ZLIBCPPFLAGS@ @NETTLECPPFLAGS@ @GPGMECPPFLAGS@ @LIBDEFLATECPPFLAGS@
#libsecrecy_la_CXXFLAGS = @LIBSECRECYCXXFLAGS@ ${AM_CXXFLAGS} @WARNCXXFLAGS@
#libsecrecy_la_LDFLAGS = @LIBSECRECYLDFLAGS@ -version-info ${LIBRARY_VERSION} @NETTLELDFLAGS@ @GPGMELDFLAGS@ @LIBDEFLATELDFLAGS@
@@ -43,6 +47,7 @@ libsecrecy_include_HEADERS=\
libsecrecy/LockedMemory.hpp \
libsecrecy/NumToHex.hpp \
libsecrecy/RawKey.hpp \
+ libsecrecy/SecrecyKeyValueStore.hpp \
libsecrecy/Yarrow.hpp
EXTRA_PROGRAMS = #
=====================================
src/apps/secrecy.1
=====================================
@@ -0,0 +1,262 @@
+.TH SECRECY 1 2020-11-13 GNU "User's Manual"
+.SH NAME
+.B secrecy
+\- libsecrecy encryption and key management tool
+.SH SYNOPSIS
+.B secrecy createKey
+.I cipher gpgid keyname
+.PP
+.B secrecy encrypt
+.RI [ keyhash | keyname ]
+.PP
+.B secrecy decrypt
+.PP
+.B secrecy exportKey
+.RI [ keyhash | keyname ]
+.I gpgid
+.PP
+.B secrecy importKey
+.I gpgid
+.PP
+.B secrecy listKeys
+.PP
+.B secrecy setDefaultKey
+.I keyname
+.SH DESCRIPTION
+.PP
+The
+.B libsecrecy
+distribution comes with a command line tool called
+.BR secrecy .
+This tool currently has seven subcommands:
+.BR createKey ,
+.BR encrypt ,
+.BR decrypt ,
+.BR exportKey ,
+.BR importKey ,
+.B listKeys
+and
+.BR setDefaultKey .
+.PP
+The program
+.B secrecy
+accepts several subcommands.
+It is to be noted that, currently,
+.B secrecy
+has no arguments for reading and writing any file.
+One has to rely on the shell capabilities to read and write plain files,
+encrypted files,
+and key exports,
+using pipes and redirection operators.
+Subcommands are the following:
+.TP
+\fBsecrecy createKey\fI cipher gpgid keyname\fR
+create keys for the
+.BR libsecrecy ,
+where
+.I cipher
+can currently take the values
+.BR AES128 ,
+.B AES192
+or
+.BR AES256 ,
+.I gpgid
+needs to be a valid id (normally an email address) present as a secret key in
+.BR gpg (1)'s
+keyring,
+which can be used for securely storing the AES key for use by
+.BR libsecrecy ,
+and
+.I keyname
+can be chosen as a human readable name for the key created,
+for instance "mykey".
+The program outputs a key hash in the form of a hexadecimal encoded string.
+Either this key hash or the key name given can to be provided to the encrypt command of
+.B secrecy
+for encrypting files using the newly created key.
+.TP
+\fBsecrecy encrypt\fR [\fIkeyhash\fR|\fIkeyname\fR]
+This subcommand allows one to encrypt files.
+.IR keyhash / keyname
+is either the hexadecimal string which was printed by
+.B createKey
+when creating the key,
+or the name given to
+.B createKey
+when creating the key.
+If the string provided is empty,
+then the default key name is used if any has been set;
+see
+.BR setDefaultKey .
+Note that this command needs to decrypt the key from it's
+.BR gpg (1)
+encoded form,
+so you will need to provide the respective passphrase in some form.
+.TP
+\fBsecrecy decrypt\fR
+This subcommand allows one to decrypt files.
+It needs to decrypt the key from it's
+.BR gpg (1)
+encoded form,
+so you will need to provide the respective passphrase in some form.
+Note that you do not need to provide the
+.I keyhash
+for decryption as this information is provided inside the encrypted file..
+.TP
+\fBsecrecy exportKey\fR [\fIkeyname\fR|\fIkeyhash\fR] \fIgpgid\fR
+Export to an encrypted transfer format,
+for passing data on to third parties,
+via the
+.B exportKey
+command of
+.BR secrecy .
+.I keyname
+or
+.I keyhash
+are valid key name or hash respectively,
+and
+.I gpgid
+is a string identifying the recipient of the key.
+The public key of
+.I gpgid
+needs to be available in
+.BR gpg 's
+key database.
+.TP
+\fBsecrecry importKey \fIgpgid\fR
+Import a key from the format produced by the
+.B exportKey
+command using the
+.B importKey
+command,
+where
+.I gpgid
+designates the
+.B gpg
+key which will be used to locally encrypt the key for storing it in
+.BR libsecrecy 's
+database.
+.TP
+.B secrecy listKeys
+List installed keys. It prints a tabulation separated table such that the first column contains the key names and the second the respective key hash values.
+.TP
+\fBsecrecy setDefaultKey \fIkeyname\fR
+Change the default key. The default key is used when an empty
+.I keyname
+is used for running any command accepting a key name,
+with the obvious exceptions of
+.B createKey
+and
+.BR setDefaultKey .
+.PP
+.SH FILES
+.PP
+AES keys are stored encrypted using
+.BR gpg (1)
+via
+.BR gpgme .
+Each key is assigned a hash
+.I H
+value at creation time.
+.I H
+is computed as the SHA256 checksum of a randomly generated sequence.
+Keys are stored and searched for in the directory set in the environment variable
+.IR LIBSECRECY_KEYDIR .
+If this variable is not set,
+then the subdirectory
+.B .libsecrecy
+inside the current users home directory,
+designated by the environment variable
+.IR HOME ,
+is used.
+Inside this directory the key for hash
+.I H
+is stored in the file
+.BR hash/H ,
+otherwise said:
+.BR hash/3E35C013C66C66B09E3E0B923451530C62D4346D9F5165906FC94B9B4D35E28E ,
+where the respective files are encrypted using
+.BR gpgme .
+The secret key used for this encryption can be set at key creation time.
+.PP
+.SH EXAMPLES
+.PP
+Create an
+.I AES256
+key using your GPG ID,
+for instance
+.IR foo at example.org ,
+and call it
+.IR mykey :
+.PP
+.EX
+ $ secrecy createKey AES256 foo at example.org mykey
+ 3E35C013C66C66B09E3E0B923451530C62D4346D9F5165906FC94B9B4D35E28E
+.EE
+.PP
+List available keys:
+.PP
+.EX
+ $ secrecy listKeys
+ mykey 3E35C013C66C66B09E3E0B923451530C62D4346D9F5165906FC94B9B4D35E28E
+.EE
+.PP
+Set
+.I mykey
+as default key:
+.PP
+.EX
+ $ secrecy setDefaultKey mykey
+.EE
+.PP
+Encrypt
+.I file
+into
+.IR file.encrypted ,
+using the default key:
+.PP
+.EX
+ $ secrecy encrypt < file > file.encrypted
+.EE
+.PP
+Decrypt
+.I file.encrypted
+into
+.IR file.decrypted ,
+using the default key:
+.PP
+.EX
+ $ secrecy decrypt < file.encrypted > file.decrypted
+.EE
+.PP
+Prepare an export of
+.I mykey
+for use by the person behind GPG ID
+.IR bar at example.org ,
+whose public key should be accessible in the user's
+.BR gpg (1)
+keyring.
+The key will be exported into the file
+.IR export.key :
+.PP
+.EX
+ $ secrecy exportKey mykey bar at example.org > export.key
+.EE
+.PP
+.SH AUTHORS
+.PP
+.B secrecy
+is a program part of the
+.BR libsecrecy ,
+written by German Tischler-Höhle <germant at miltenyibiotec.de>.
+.PP
+The present manual page is written by Étienne Mollier <emollier at debian.org> for the Debian project.
+.SH SEE ALSO
+.PP
+See the
+.UR https://gnupg.org/documentation/manuals/gnupg/OpenPGP-Key-Management.html#OpenPGP-Key-Management
+GnuPG documentation relative to key management
+.UE
+for creating and handling
+.BR gpg (1)
+keys.
=====================================
src/apps/secrecy.cpp
=====================================
@@ -50,14 +50,14 @@ void writeKey(std::string const & gpgrecipient, std::string const & keyname)
// read back key and check for equality
std::string const keyfiledata = libsecrecy::RawKeyBase::readKeyData(hexhash,false /* do not try to resolve name */);
std::istringstream keydataistr(keyfiledata);
- libsecrecy::RawKeyBase::expectMagic(keydataistr);
- std::string const keycipher = libsecrecy::GCMStreamBase::readString(keydataistr);
- std::string const rkeyname = libsecrecy::GCMStreamBase::readString(keydataistr);
+
+ std::shared_ptr<libsecrecy::SecrecyKeyValueStore> SKV(libsecrecy::RawKeyBase::loadMetaData(keydataistr));
+ std::string const keycipher = SKV->getStringValue("cipher");
if ( keycipher != K.getPrefix() )
throw std::runtime_error("Decoded key does not match encoded key (wrong cipher)");
- key_type KB(gpgme,keydataistr);
+ key_type KB(gpgme,keydataistr,*SKV);
bool const eq = (K == KB);
@@ -110,12 +110,14 @@ static std::string getExportedKeyMagic()
}
template<typename key_type>
-void exportKey(std::string const & sgpgid, std::istream & keydataistr, std::string const & keyname)
+void exportKey(std::string const & sgpgid, std::istream & keydataistr, libsecrecy::SecrecyKeyValueStore const & SKV)
{
libsecrecy::GPGMEContext gpgme;
- key_type KB(gpgme,keydataistr);
+ key_type KB(gpgme,keydataistr,SKV);
std::shared_ptr< libsecrecy::LockedMemory<char> > const keyhex = KB.keyToHex();
+ std::string const keyname = SKV.getStringValue("keyname");
+
std::ostringstream ostr;
libsecrecy::GCMStreamBase::writeString(ostr,getExportedKeyMagic());
libsecrecy::GCMStreamBase::writeString(ostr,KB.getPrefix());
@@ -180,21 +182,21 @@ int exportKey(char const * progname, int argc, char * argv[])
// read back key and check for equality
std::string const keyfiledata = libsecrecy::RawKeyBase::readKeyData(skeyname,true /* try to resolve name */);
std::istringstream keydataistr(keyfiledata);
- libsecrecy::RawKeyBase::expectMagic(keydataistr);
- std::string const keycipher = libsecrecy::GCMStreamBase::readString(keydataistr);
- std::string const rkeyname = libsecrecy::GCMStreamBase::readString(keydataistr);
+
+ std::shared_ptr<libsecrecy::SecrecyKeyValueStore> SKV(libsecrecy::RawKeyBase::loadMetaData(keydataistr));
+ std::string const keycipher = SKV->getStringValue("cipher");
if ( keycipher == "AES256" )
{
- exportKey<libsecrecy::AES256EncryptKey>(sgpgid,keydataistr,rkeyname);
+ exportKey<libsecrecy::AES256EncryptKey>(sgpgid,keydataistr,*SKV);
}
else if ( keycipher == "AES192" )
{
- exportKey<libsecrecy::AES192EncryptKey>(sgpgid,keydataistr,rkeyname);
+ exportKey<libsecrecy::AES192EncryptKey>(sgpgid,keydataistr,*SKV);
}
else if ( keycipher == "AES128" )
{
- exportKey<libsecrecy::AES128EncryptKey>(sgpgid,keydataistr,rkeyname);
+ exportKey<libsecrecy::AES128EncryptKey>(sgpgid,keydataistr,*SKV);
}
else
{
=====================================
src/libsecrecy/AESEncryptKey.hpp
=====================================
@@ -81,9 +81,9 @@ namespace libsecrecy
set_encrypt_key_func(ctx,kptr->get());
}
- EncryptKey(libsecrecy::GPGMEContext & context, std::istream & in) : kptr(new raw_key_type), lctx(1), ctx(lctx.get())
+ EncryptKey(libsecrecy::GPGMEContext & context, std::istream & in, SecrecyKeyValueStore const & SKV) : kptr(new raw_key_type), lctx(1), ctx(lctx.get())
{
- kptr->readKey(context,in);
+ kptr->readKey(context,in,SKV);
set_encrypt_key_func(ctx,kptr->get());
}
=====================================
src/libsecrecy/GCMFactoryBase.hpp
=====================================
@@ -41,9 +41,10 @@ namespace libsecrecy
{
std::string const keyfiledata = RawKeyBase::readKeyData(hexhash,resolve);
std::istringstream keydataistr(keyfiledata);
- RawKeyBase::expectMagic(keydataistr);
- std::string const scipher = GCMStreamBase::readString(keydataistr);
- std::string const keyname = GCMStreamBase::readString(keydataistr);
+ std::shared_ptr<libsecrecy::SecrecyKeyValueStore> SKV(libsecrecy::RawKeyBase::loadMetaData(keydataistr));
+ std::string const scipher = SKV->getStringValue("cipher");
+ std::string const skeyname = SKV->getStringValue("keyname");
+
std::string keyhex;
std::shared_ptr<RawKeyBase> RKB;
@@ -52,7 +53,7 @@ namespace libsecrecy
typedef AES128EncryptKey key_type;
typedef key_type::raw_key_type raw_key_type;
std::shared_ptr<RawKeyBase> TRKB(new raw_key_type);
- dynamic_cast<raw_key_type *>(TRKB.get())->readKey(context,keydataistr);
+ dynamic_cast<raw_key_type *>(TRKB.get())->readKey(context,keydataistr,*SKV);
keyhex = dynamic_cast<raw_key_type *>(TRKB.get())->hashToHex();
RKB = TRKB;
}
@@ -61,7 +62,7 @@ namespace libsecrecy
typedef AES192EncryptKey key_type;
typedef key_type::raw_key_type raw_key_type;
std::shared_ptr<RawKeyBase> TRKB(new raw_key_type);
- dynamic_cast<raw_key_type *>(TRKB.get())->readKey(context,keydataistr);
+ dynamic_cast<raw_key_type *>(TRKB.get())->readKey(context,keydataistr,*SKV);
keyhex = dynamic_cast<raw_key_type *>(TRKB.get())->hashToHex();
RKB = TRKB;
}
@@ -70,12 +71,12 @@ namespace libsecrecy
typedef AES256EncryptKey key_type;
typedef key_type::raw_key_type raw_key_type;
std::shared_ptr<RawKeyBase> TRKB(new raw_key_type);
- dynamic_cast<raw_key_type *>(TRKB.get())->readKey(context,keydataistr);
+ dynamic_cast<raw_key_type *>(TRKB.get())->readKey(context,keydataistr,*SKV);
keyhex = dynamic_cast<raw_key_type *>(TRKB.get())->hashToHex();
RKB = TRKB;
}
- return RawKeyObject(RKB,scipher,keyname,keyhex);
+ return RawKeyObject(RKB,scipher,skeyname,keyhex);
}
static RawKeyObject obtainKey(
=====================================
src/libsecrecy/GCMStreamHeader.hpp
=====================================
@@ -26,14 +26,12 @@
#if ! defined(LIBSECRECY_GCMSTREAMHEADER_HPP)
#define LIBSECRECY_GCMSTREAMHEADER_HPP
-#include <libsecrecy/GCMStreamBase.hpp>
+#include <libsecrecy/SecrecyKeyValueStore.hpp>
#include <libsecrecy/GCMIV.hpp>
-#include <map>
-#include <vector>
namespace libsecrecy
{
- struct GCMStreamHeader : public GCMStreamBase
+ struct GCMStreamHeader : public SecrecyKeyValueStore
{
std::map<std::string,std::string> M;
@@ -46,71 +44,9 @@ namespace libsecrecy
{}
GCMStreamHeader(std::istream & in)
+ : SecrecyKeyValueStore(in,getMagic())
{
- char const * magic = getMagic();
- while ( *magic )
- {
- char const c = getChecked(in);
- char const e = *(magic++);
- if ( c != e )
- {
- throw std::runtime_error("libsecrecy::GCMStreamHeader: mismatch in file magic");
- }
- }
- std::size_t const numfields = readNumber(in);
-
- for ( std::size_t i = 0; i < numfields; ++i )
- {
- std::string const key = readString(in);
- std::string const value = readString(in);
- M[key] = value;
- }
- }
-
- std::string toString() const
- {
- std::ostringstream ostr;
- for ( auto const it : M )
- ostr << "M[" << it.first << "]=" << it.second << "\n";
- return ostr.str();
- }
-
- std::vector<uint8_t> decodeHexField(std::string const & key) const
- {
- auto const it = M.find(key);
-
- if ( it == M.end() )
- throw std::runtime_error(std::string("libsecrecy::GCMStreamHeader::decodeHexField: key ") + key + " is not present");
-
- std::string const shex = it->second;
-
- if ( shex.size() % 2 != 0 )
- {
- std::ostringstream ostr;
- ostr << "libsecrecy::GCMStreamHeader::decodeHexField: value " << shex << " for key " << key << " has uneven length";
- throw std::runtime_error(ostr.str());
- }
-
- std::vector<uint8_t> V;
- std::string::const_iterator sit = shex.begin();
- while ( sit != shex.end() )
- {
- char const chigh = *(sit++);
- assert ( sit != shex.end() );
- char const clow = *(sit++);
- V.push_back((NumToHex::hexToNum(chigh) << 4) | NumToHex::hexToNum(clow));
- }
-
- return V;
- }
-
- std::pair < std::shared_ptr<uint8_t[]>, std::size_t > decodeHexFieldAsArray(std::string const & key) const
- {
- std::vector<uint8_t> const V(decodeHexField(key));
- std::shared_ptr<uint8_t[]> ptr(new uint8_t[V.size()]);
- std::copy(V.begin(),V.end(),ptr.get());
- return std::make_pair(ptr,V.size());
}
std::pair < std::shared_ptr<uint8_t[]>, std::size_t > getAuthData() const
@@ -130,97 +66,14 @@ namespace libsecrecy
{
std::size_t r = 0;
- // write magic
- char const * magic = getMagic();
- std::size_t const l_magic = strlen(magic);
- out.write(magic,l_magic);
- r += l_magic;
-
- // number of key=value pairs
- r += writeNumber(out,M.size());
-
- for ( auto it : M )
- {
- r += writeString(out,it.first);
- r += writeString(out,it.second);
- }
-
- if ( ! out )
- {
- throw std::runtime_error("libsecrecy::GCMStreamHeader::serialise: failed to write data");
- }
+ r += SecrecyKeyValueStore::serialise(out,getMagic());
return r;
}
std::size_t size() const
{
- std::ostringstream ostr;
- std::size_t const r = serialise(ostr);
-
- if ( r != ostr.str().size() )
- {
- std::ostringstream eostr;
- eostr << "libsecrecy::GCMStreamHeader::size: mismatch between computed r=" << r << " and actual " << ostr.str().size();
- throw std::runtime_error(eostr.str());
- }
-
- return r;
- }
-
- void setStringValue(std::string const & key, std::string const & value)
- {
- M[key] = value;
- }
-
- template<typename value_type>
- void setNumericalValue(std::string const & key, value_type const & v)
- {
- std::ostringstream ostr;
- ostr << v;
- setStringValue(key,ostr.str());
- }
-
- std::string getStringValue(std::string const & key) const
- {
- auto const it = M.find(key);
-
- if ( it == M.end() )
- {
- std::ostringstream ostr;
- ostr << "libsecrecy::GCMStreamHeader::getStringValue: field " << key << " is not present";
- throw std::runtime_error(ostr.str());
- }
-
- return it->second;
- }
-
- template<typename value_type>
- value_type getParsedValue(std::string const & key) const
- {
- auto const it = M.find(key);
-
- if ( it == M.end() )
- {
- std::ostringstream ostr;
- ostr << "libsecrecy::GCMStreamHeader::getParsedValue: field " << key << " is not present";
- throw std::runtime_error(ostr.str());
- }
-
- std::istringstream istr(it->second);
- value_type v;
- istr >> v;
-
- if ( istr && istr.peek() == std::istream::traits_type::eof() )
- {
- return v;
- }
- else
- {
- std::ostringstream ostr;
- ostr << "libsecrecy::GCMStreamHeader::getParsedValue: field " << key << " has unparsable value " << it->second;
- throw std::runtime_error(ostr.str());
- }
+ return SecrecyKeyValueStore::size(getMagic());
}
};
}
=====================================
src/libsecrecy/RawKey.hpp
=====================================
@@ -29,6 +29,7 @@
#include <libsecrecy/GPGMEContext.hpp>
#include <libsecrecy/Yarrow.hpp>
#include <libsecrecy/GCMStreamBase.hpp>
+#include <libsecrecy/SecrecyKeyValueStore.hpp>
#include <nettle/aes.h>
#include <cstdlib>
#include <filesystem>
@@ -236,17 +237,20 @@ namespace libsecrecy
{
std::string const keynamedir = getKeyNameDirectory();
- for ( auto const & p : std::filesystem::directory_iterator(keynamedir) )
+ if ( std::filesystem::exists(keynamedir) )
{
- std::filesystem::path const keypath = p.path();
- std::string hash;
-
- if ( std::filesystem::exists(keypath) && std::filesystem::is_symlink(keypath) )
+ for ( auto const & p : std::filesystem::directory_iterator(keynamedir) )
{
- hash = static_cast<std::string>(std::filesystem::path(followSymLink(keypath)).filename());
- }
+ std::filesystem::path const keypath = p.path();
+ std::string hash;
+
+ if ( std::filesystem::exists(keypath) && std::filesystem::is_symlink(keypath) )
+ {
+ hash = static_cast<std::string>(std::filesystem::path(followSymLink(keypath)).filename());
+ }
- out << static_cast<std::string>(keypath.filename()) << "\t" << hash << "\n";
+ out << static_cast<std::string>(keypath.filename()) << "\t" << hash << "\n";
+ }
}
}
@@ -289,6 +293,12 @@ namespace libsecrecy
return static_cast<std::string>(curpath);
}
+ static std::shared_ptr<SecrecyKeyValueStore> loadMetaData(std::istream & in)
+ {
+ std::shared_ptr<SecrecyKeyValueStore> ptr(new SecrecyKeyValueStore(in,getMagic()));
+ return ptr;
+ }
+
static std::string readKeyData(std::string hexhash, bool tryname)
{
if ( !hexhash.size() && tryname )
@@ -391,18 +401,6 @@ namespace libsecrecy
{
return "LIBSECRECY_KEY";
}
-
- static void expectMagic(std::istream & in)
- {
- std::string const magic = GCMStreamBase::readString(in);
-
- if ( magic != getMagic() )
- {
- std::ostringstream estr;
- estr << "libsecrecy::RawKey::expectMagic: mismatch in file identifier";
- throw std::runtime_error(estr.str());
- }
- }
};
struct RawKeyObject
@@ -619,13 +617,12 @@ namespace libsecrecy
std::ostringstream sstr;
- GCMStreamBase::writeString(sstr,getMagic());
- // write prefix / cipher
- GCMStreamBase::writeString(sstr,cipher);
- // write name value
- GCMStreamBase::writeString(sstr,keyname);
- // write hash value
- GCMStreamBase::writeString(sstr,hashToHex());
+ SecrecyKeyValueStore SKV;
+ SKV.setStringValue("cipher",cipher);
+ SKV.setStringValue("keyname",keyname);
+ SKV.setStringValue("hash",hashToHex());
+ SKV.serialise(sstr,getMagic());
+
// write encrypted key
context.encrypt(
reinterpret_cast<char const *>(L.begin()),
@@ -681,9 +678,9 @@ namespace libsecrecy
std::filesystem::current_path(lcwd);
}
- void readKey(libsecrecy::GPGMEContext & context, std::istream & in)
+ void readKey(libsecrecy::GPGMEContext & context, std::istream & in, SecrecyKeyValueStore const & SKV)
{
- std::string const shexhash = GCMStreamBase::readString(in);
+ std::string const shexhash = SKV.getStringValue("hash");
if ( shexhash.size() != 2*digestsize )
{
=====================================
src/libsecrecy/SecrecyKeyValueStore.hpp
=====================================
@@ -0,0 +1,208 @@
+/**
+ * Copyright 2020 German Tischler-Höhle
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ **/
+#if ! defined(LIBSECRECY_SECRECYKEYVALUESTORE_HPP)
+#define LIBSECRECY_SECRECYKEYVALUESTORE_HPP
+
+#include <libsecrecy/GCMStreamBase.hpp>
+#include <map>
+#include <vector>
+
+namespace libsecrecy
+{
+ struct SecrecyKeyValueStore : public GCMStreamBase
+ {
+ std::map<std::string,std::string> M;
+
+ SecrecyKeyValueStore()
+ {}
+ SecrecyKeyValueStore(std::istream & in, std::string const & smagic)
+ {
+ char const * magic = smagic.c_str();
+
+ while ( *magic )
+ {
+ char const c = getChecked(in);
+ char const e = *(magic++);
+ if ( c != e )
+ {
+ throw std::runtime_error("libsecrecy::SecrecyKeyValueStore: mismatch in file magic");
+ }
+ }
+
+ std::size_t const numfields = readNumber(in);
+
+ for ( std::size_t i = 0; i < numfields; ++i )
+ {
+ std::string const key = readString(in);
+ std::string const value = readString(in);
+ M[key] = value;
+ }
+ }
+
+ std::string toString() const
+ {
+ std::ostringstream ostr;
+ for ( auto const & it : M )
+ ostr << "M[" << it.first << "]=" << it.second << "\n";
+ return ostr.str();
+ }
+
+ std::vector<uint8_t> decodeHexField(std::string const & key) const
+ {
+ auto const it = M.find(key);
+
+ if ( it == M.end() )
+ throw std::runtime_error(std::string("libsecrecy::SecrecyKeyValueStore::decodeHexField: key ") + key + " is not present");
+
+ std::string const shex = it->second;
+
+ if ( shex.size() % 2 != 0 )
+ {
+ std::ostringstream ostr;
+ ostr << "libsecrecy::SecrecyKeyValueStore::decodeHexField: value " << shex << " for key " << key << " has uneven length";
+ throw std::runtime_error(ostr.str());
+ }
+
+ std::vector<uint8_t> V;
+ std::string::const_iterator sit = shex.begin();
+ while ( sit != shex.end() )
+ {
+ char const chigh = *(sit++);
+ assert ( sit != shex.end() );
+ char const clow = *(sit++);
+ V.push_back((NumToHex::hexToNum(chigh) << 4) | NumToHex::hexToNum(clow));
+ }
+
+ return V;
+ }
+
+ std::pair < std::shared_ptr<uint8_t[]>, std::size_t > decodeHexFieldAsArray(std::string const & key) const
+ {
+ std::vector<uint8_t> const V(decodeHexField(key));
+ std::shared_ptr<uint8_t[]> ptr(new uint8_t[V.size()]);
+ std::copy(V.begin(),V.end(),ptr.get());
+ return std::make_pair(ptr,V.size());
+ }
+
+ std::size_t serialise(std::ostream & out, std::string const & smagic) const
+ {
+ std::size_t r = 0;
+
+ // write magic
+ char const * magic = smagic.c_str();
+ std::size_t const l_magic = strlen(magic);
+ out.write(magic,l_magic);
+ r += l_magic;
+
+ // number of key=value pairs
+ r += writeNumber(out,M.size());
+
+ for ( auto it : M )
+ {
+ r += writeString(out,it.first);
+ r += writeString(out,it.second);
+ }
+
+ if ( ! out )
+ {
+ throw std::runtime_error("libsecrecy::SecrecyKeyValueStore::serialise: failed to write data");
+ }
+
+ return r;
+ }
+
+ std::size_t size(std::string const & smagic) const
+ {
+ std::ostringstream ostr;
+ std::size_t const r = serialise(ostr,smagic);
+
+ if ( r != ostr.str().size() )
+ {
+ std::ostringstream eostr;
+ eostr << "libsecrecy::SecrecyKeyValueStore::size: mismatch between computed r=" << r << " and actual " << ostr.str().size();
+ throw std::runtime_error(eostr.str());
+ }
+
+ return r;
+ }
+
+ void setStringValue(std::string const & key, std::string const & value)
+ {
+ M[key] = value;
+ }
+
+ template<typename value_type>
+ void setNumericalValue(std::string const & key, value_type const & v)
+ {
+ std::ostringstream ostr;
+ ostr << v;
+ setStringValue(key,ostr.str());
+ }
+
+ std::string getStringValue(std::string const & key) const
+ {
+ auto const it = M.find(key);
+
+ if ( it == M.end() )
+ {
+ std::ostringstream ostr;
+ ostr << "libsecrecy::SecrecyKeyValueStore::getStringValue: field " << key << " is not present";
+ throw std::runtime_error(ostr.str());
+ }
+
+ return it->second;
+ }
+
+ template<typename value_type>
+ value_type getParsedValue(std::string const & key) const
+ {
+ auto const it = M.find(key);
+
+ if ( it == M.end() )
+ {
+ std::ostringstream ostr;
+ ostr << "libsecrecy::SecrecyKeyValueStore::getParsedValue: field " << key << " is not present";
+ throw std::runtime_error(ostr.str());
+ }
+
+ std::istringstream istr(it->second);
+ value_type v;
+ istr >> v;
+
+ if ( istr && istr.peek() == std::istream::traits_type::eof() )
+ {
+ return v;
+ }
+ else
+ {
+ std::ostringstream ostr;
+ ostr << "libsecrecy::SecrecyKeyValueStore::getParsedValue: field " << key << " has unparsable value " << it->second;
+ throw std::runtime_error(ostr.str());
+ }
+ }
+ };
+}
+#endif
=====================================
src/libsecrecy/libsecrecy.hpp deleted
=====================================
@@ -1,69 +0,0 @@
-/**
- * Copyright 2020 German Tischler-Höhle
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- **/
-
-/**
- * headers
- **/
-
-/**
- * functions
- **/
-
-/**
- * functions blocks
- **/
-
-/**
- * compiler features
- **/
-
-/**
- * third party libraries
- **/
-
-/**
- * capabilities in third party libraries
- **/
-
-/**
- * flag constants
- **/
-
-/**
- * numeric constants
- **/
-
-/**
- * compilation flags
- **/
-
-/**
- * enable/disable feature flags
- **/
-
-/**
- * info flags
- **/
View it on GitLab: https://salsa.debian.org/med-team/libsecrecy/-/commit/d9b3411bd0a3f9d685041e80caed60b755e041f2
--
View it on GitLab: https://salsa.debian.org/med-team/libsecrecy/-/commit/d9b3411bd0a3f9d685041e80caed60b755e041f2
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20211023/88d96fcf/attachment-0001.htm>
More information about the debian-med-commit
mailing list