Skip to content
Snippets Groups Projects
Select Git revision
  • 7efeac2ae406f33f0dfadbbd276212117173b3db
  • master default protected
  • release/202005
  • release/202001
  • release/201912
  • release/windows-test/201910
  • release/201908
  • release/201906
  • release/201905
  • release/201904
  • release/201903
  • release/201902
  • release/201901
  • release/201812
  • release/201811
  • release/201808
  • wip/patches_poly_2017/cedryk_doucet/abderahmane_bouziane
  • releases/beta1
  • android/release_461
  • android/release_460
  • android/release_459
  • android/release_458
  • android/release_457
  • android/release_456
  • android/release_455
  • android/release_454
  • android/release_453
  • android/release_452
  • android/release_451
  • android/release_450
  • android/release_449
  • android/release_448
  • android/release_447
  • android/release_446
  • android/release_445
  • android/release_444
  • android/release_443
  • android/release_442
38 results

ContactDetailsActivity.kt

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    crypto.h 11.93 KiB
    /*
     *  Copyright (C) 2014-2016 Savoir-faire Linux Inc.
     *  Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
     *
     *  This program is free software; you can redistribute it and/or modify
     *  it under the terms of the GNU General Public License as published by
     *  the Free Software Foundation; either version 3 of the License, or
     *  (at your option) any later version.
     *
     *  This program is distributed in the hope that it will be useful,
     *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     *  GNU General Public License for more details.
     *
     *  You should have received a copy of the GNU General Public License
     *  along with this program; if not, write to the Free Software
     *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
     */
    
    #pragma once
    
    #include "infohash.h"
    #include "utils.h"
    
    extern "C" {
    #include <gnutls/gnutls.h>
    #include <gnutls/abstract.h>
    #include <gnutls/x509.h>
    }
    
    #include <vector>
    #include <memory>
    
    #ifdef _WIN32
    #include <iso646.h>
    #endif
    
    namespace dht {
    namespace crypto {
    
    class OPENDHT_PUBLIC CryptoException : public std::runtime_error {
        public:
            CryptoException(const std::string& str) : std::runtime_error(str) {};
    };
    
    /**
     * Exception thrown when a decryption error happened.
     */
    class OPENDHT_PUBLIC DecryptError : public CryptoException {
        public:
            DecryptError(const std::string& str = "") : CryptoException(str) {};
    };
    
    struct PrivateKey;
    struct Certificate;
    
    using Identity = std::pair<std::shared_ptr<PrivateKey>, std::shared_ptr<Certificate>>;
    
    /**
     * A public key.
     */
    struct OPENDHT_PUBLIC PublicKey
    {
        PublicKey() {}
    
        /**
         * Takes ownership of an existing gnutls_pubkey.
         */
        PublicKey(gnutls_pubkey_t k) : pk(k) {}
        PublicKey(const Blob& pk);
        PublicKey(PublicKey&& o) noexcept : pk(o.pk) { o.pk = nullptr; };
    
        ~PublicKey();
        explicit operator bool() const { return pk; }
        bool operator ==(const PublicKey& o) const {
            return pk == o.pk || getId() == o.getId();
        }
        bool operator !=(const PublicKey& o) const {
            return !(*this == o);
        }
    
        PublicKey& operator=(PublicKey&& o) noexcept;
    
        InfoHash getId() const;
        bool checkSignature(const Blob& data, const Blob& signature) const;
        Blob encrypt(const Blob&) const;
    
        void pack(Blob& b) const;
        void unpack(const uint8_t* dat, size_t dat_size);
    
        template <typename Packer>
        void msgpack_pack(Packer& p) const
        {
            Blob b;
            pack(b);
            p.pack_bin(b.size());
            p.pack_bin_body((const char*)b.data(), b.size());
        }
    
        void msgpack_unpack(msgpack::object o);
    
        gnutls_pubkey_t pk {};
    private:
        PublicKey(const PublicKey&) = delete;
        PublicKey& operator=(const PublicKey&) = delete;
        void encryptBloc(const uint8_t* src, size_t src_size, uint8_t* dst, size_t dst_size) const;
    };
    
    /**
     * A private key, including the corresponding public key.
     */
    struct OPENDHT_PUBLIC PrivateKey
    {
        PrivateKey();
        //PrivateKey(gnutls_privkey_t k) : key(k) {}
    
        /**
         * Takes ownership of an existing gnutls_x509_privkey.
         */
        PrivateKey(gnutls_x509_privkey_t k);
    
        PrivateKey(PrivateKey&& o) noexcept;
        PrivateKey& operator=(PrivateKey&& o) noexcept;
    
        PrivateKey(const Blob& import, const std::string& password = {});
        ~PrivateKey();
        explicit operator bool() const { return key; }
        PublicKey getPublicKey() const;
        Blob serialize(const std::string& password = {}) const;
    
        /**
         * Sign the provided binary object.
         * @returns the signature data.
         */
        Blob sign(const Blob&) const;
    
        /**
         * Try to decrypt the provided cypher text.
         * In case of failure a CryptoException is thrown.
         * @returns the decrypted data.
         */
        Blob decrypt(const Blob& cypher) const;
    
        /**
         * Generate a new RSA key pair
         * @param key_length : size of the modulus in bits
         *      Minimim value: 2048
         *      Recommended values: 4096, 8192
         */
        static PrivateKey generate(unsigned key_length = 4096);
        static PrivateKey generateEC();
    
        gnutls_privkey_t key {};
        gnutls_x509_privkey_t x509_key {};
    private:
        PrivateKey(const PrivateKey&) = delete;
        PrivateKey& operator=(const PrivateKey&) = delete;
        Blob decryptBloc(const uint8_t* src, size_t src_size) const;
    
        //friend dht::crypto::Identity dht::crypto::generateIdentity(const std::string&, dht::crypto::Identity, unsigned key_length);
    };
    
    struct OPENDHT_PUBLIC Certificate {
        Certificate() {}
    
        /**
         * Take ownership of existing gnutls structure
         */
        Certificate(gnutls_x509_crt_t crt) : cert(crt) {}
    
        Certificate(Certificate&& o) noexcept : cert(o.cert), issuer(std::move(o.issuer)) { o.cert = nullptr; };
    
        /**
         * Import certificate (PEM or DER) or certificate chain (PEM),
         * ordered from subject to issuer
         */
        Certificate(const Blob& crt);
        Certificate(const uint8_t* dat, size_t dat_size) {
            unpack(dat, dat_size);
        }
    
        /**
         * Import certificate chain (PEM or DER),
         * ordered from subject to issuer
         */
        template<typename Iterator>
        Certificate(const Iterator& begin, const Iterator& end) {
            unpack(begin, end);
        }
    
        /**
         * Import certificate chain (PEM or DER),
         * ordered from subject to issuer
         */
        template<typename Iterator>
        Certificate(const std::vector<std::pair<Iterator, Iterator>>& certs) {
            unpack(certs);
        }
    
        Certificate& operator=(Certificate&& o) noexcept;
        ~Certificate();
    
        void pack(Blob& b) const;
        void unpack(const uint8_t* dat, size_t dat_size);
        Blob getPacked() const {
            Blob b;
            pack(b);
            return b;
        }
    
        /**
         * Import certificate chain (PEM or DER).
         * Certificates are not checked during import.
         *
         * Iterator is the type of an iterator or pointer to
         * gnutls_x509_crt_t or Blob instances to import, that should be
         * ordered from subject to issuer.
         */
        template<typename Iterator>
        void unpack(const Iterator& begin, const Iterator& end)
        {
            std::shared_ptr<Certificate> tmp_subject {};
            std::shared_ptr<Certificate> first {};
            for (Iterator icrt = begin; icrt < end; ++icrt) {
                auto tmp_crt = std::make_shared<Certificate>(*icrt);
                if (tmp_subject)
                    tmp_subject->issuer = tmp_crt;
                tmp_subject = std::move(tmp_crt);
                if (!first)
                    first = tmp_subject;
            }
            *this = first ? std::move(*first) : Certificate();
        }
    
        /**
         * Import certificate chain (PEM or DER).
         * Certificates are not checked during import.
         *
         * Iterator is the type of an iterator or pointer to the bytes of
         * the certificates to import.
         *
         * @param certs list of (begin, end) iterator pairs, pointing to the
         *              PEM or DER certificate data to import, that should be
         *              ordered from subject to issuer.
         */
        template<typename Iterator>
        void unpack(const std::vector<std::pair<Iterator, Iterator>>& certs)
        {
            std::shared_ptr<Certificate> tmp_issuer;
            // reverse iteration
            for (auto li = certs.rbegin(); li != certs.rend(); ++li) {
                Certificate tmp_crt;
                gnutls_x509_crt_init(&tmp_crt.cert);
                const gnutls_datum_t crt_dt {(uint8_t*)&(*li->first), (unsigned)(li->second-li->first)};
                int err = gnutls_x509_crt_import(tmp_crt.cert, &crt_dt, GNUTLS_X509_FMT_PEM);
                if (err != GNUTLS_E_SUCCESS)
                    err = gnutls_x509_crt_import(tmp_crt.cert, &crt_dt, GNUTLS_X509_FMT_DER);
                if (err != GNUTLS_E_SUCCESS)
                    throw CryptoException(std::string("Could not read certificate - ") + gnutls_strerror(err));
                tmp_crt.issuer = tmp_issuer;
                tmp_issuer = std::make_shared<Certificate>(std::move(tmp_crt));
            }
            *this = tmp_issuer ? std::move(*tmp_issuer) : Certificate();
        }
    
        template <typename Packer>
        void msgpack_pack(Packer& p) const
        {
            Blob b;
            pack(b);
            p.pack_bin(b.size());
            p.pack_bin_body((const char*)b.data(), b.size());
        }
    
        void msgpack_unpack(msgpack::object o);
    
        explicit operator bool() const { return cert; }
        PublicKey getPublicKey() const;
    
        /** Same as getPublicKey().getId() */
        InfoHash getId() const;
    
        /** Read certificate Common Name (CN) */
        std::string getName() const;
    
        /** Read certificate User ID (UID) */
        std::string getUID() const;
    
        /** Read certificate issuer Common Name (CN) */
        std::string getIssuerName() const;
    
        /** Read certificate issuer User ID (UID) */
        std::string getIssuerUID() const;
    
        enum class NameType { UNKNOWN = 0, RFC822, DNS, URI, IP };
    
        /** Read certificate alternative names */
        std::vector<std::pair<NameType, std::string>> getAltNames() const;
    
        /**
         * Returns true if the certificate is marked as a Certificate Authority.
         */
        bool isCA() const;
    
        /**
         * PEM encoded certificate.
         * If chain is true, the issuer chain will be included (default).
         */
        std::string toString(bool chain = true) const;
    
        static Certificate generate(const PrivateKey& key, const std::string& name = "dhtnode", Identity ca = {}, bool is_ca = false);
    
        gnutls_x509_crt_t cert {};
        std::shared_ptr<Certificate> issuer {};
    private:
        Certificate(const Certificate&) = delete;
        Certificate& operator=(const Certificate&) = delete;
    };
    
    
    class OPENDHT_PUBLIC RevocationList
    {
    public:
        RevocationList();
        RevocationList(const Blob& b);
        ~RevocationList();
    
        bool isRevoked(const Certificate& crt) const;
    
        void revoke(const Certificate& crt, std::chrono::system_clock::time_point t = {});
    
        /**
         * Sign this revocation list using provided key and certificate.
         */
        void sign(const PrivateKey&, const Certificate&);
        void sign(const Identity& id) { sign(*id.first, *id.second); }
    
        bool isIssuedBy(const Certificate& crt);
    
        bool isValid(const Certificate& issuer);
    
        std::string toString();
    
        gnutls_x509_crl_t get() { return crl; }
    
    private:
        gnutls_x509_crl_t crl {};
        RevocationList(const RevocationList&) = delete;
        RevocationList& operator=(const RevocationList&) = delete;
    };
    
    
    /**
     * Generate an RSA key pair (4096 bits) and a certificate.
     * @param name the name used in the generated certificate
     * @param ca if set, the certificate authority that will sign the generated certificate.
     *           If not set, the generated certificate will be a self-signed CA.
     * @param key_length stength of the generated private key (bits).
     */
    OPENDHT_PUBLIC Identity generateIdentity(const std::string& name, Identity ca, unsigned key_length, bool is_ca);
    OPENDHT_PUBLIC Identity generateIdentity(const std::string& name = "dhtnode", Identity ca = {}, unsigned key_length = 4096);
    
    
    /**
     * Performs SHA512, SHA256 or SHA1, depending on hash_length.
     * Attempts to choose an hash function with
     * output size of at least hash_length bytes, Current implementation
     * will use SHA1 for hash_length up to 20 bytes,
     * will use SHA256 for hash_length up to 32 bytes,
     * will use SHA512 for hash_length of 33 bytes and more.
     */
    OPENDHT_PUBLIC Blob hash(const Blob& data, size_t hash_length = 512/8);
    
    /**
     * Generates an encryption key from a text password,
     * making the key longer to bruteforce.
     * The generated key also depends on a unique salt value of any size,
     * that can be transmitted in clear, and will be generated if
     * not provided (32 bytes).
     */
    OPENDHT_PUBLIC Blob stretchKey(const std::string& password, Blob& salt, size_t key_length = 512/8);
    
    /**
     * AES-GCM encryption. Key must be 128, 192 or 256 bits long (16, 24 or 32 bytes).
     */
    OPENDHT_PUBLIC Blob aesEncrypt(const Blob& data, const Blob& key);
    OPENDHT_PUBLIC Blob aesEncrypt(const Blob& data, const std::string& password);
    
    /**
     * AES-GCM decryption.
     */
    OPENDHT_PUBLIC Blob aesDecrypt(const Blob& data, const Blob& key);
    OPENDHT_PUBLIC Blob aesDecrypt(const Blob& data, const std::string& password);
    
    }
    }