Explorar el Código

Implement sign and verify in crypto.

Fabio Alessandrelli hace 5 años
padre
commit
dfcc11fa52

+ 2 - 0
core/crypto/crypto.cpp

@@ -86,6 +86,8 @@ void Crypto::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("generate_random_bytes", "size"), &Crypto::generate_random_bytes);
 	ClassDB::bind_method(D_METHOD("generate_rsa", "size"), &Crypto::generate_rsa);
 	ClassDB::bind_method(D_METHOD("generate_self_signed_certificate", "key", "issuer_name", "not_before", "not_after"), &Crypto::generate_self_signed_certificate, DEFVAL("CN=myserver,O=myorganisation,C=IT"), DEFVAL("20140101000000"), DEFVAL("20340101000000"));
+	ClassDB::bind_method(D_METHOD("sign", "hash_type", "hash", "key"), &Crypto::sign);
+	ClassDB::bind_method(D_METHOD("verify", "hash_type", "hash", "signature", "key"), &Crypto::verify);
 }
 
 /// Resource loader/saver

+ 4 - 0
core/crypto/crypto.h

@@ -31,6 +31,7 @@
 #ifndef CRYPTO_H
 #define CRYPTO_H
 
+#include "core/crypto/hashing_context.h"
 #include "core/io/resource_loader.h"
 #include "core/io/resource_saver.h"
 #include "core/reference.h"
@@ -82,6 +83,9 @@ public:
 	virtual Ref<CryptoKey> generate_rsa(int p_bytes) = 0;
 	virtual Ref<X509Certificate> generate_self_signed_certificate(Ref<CryptoKey> p_key, String p_issuer_name, String p_not_before, String p_not_after) = 0;
 
+	virtual Vector<uint8_t> sign(HashingContext::HashType p_hash_type, Vector<uint8_t> p_hash, Ref<CryptoKey> p_key) = 0;
+	virtual bool verify(HashingContext::HashType p_hash_type, Vector<uint8_t> p_hash, Vector<uint8_t> p_signature, Ref<CryptoKey> p_key) = 0;
+
 	Crypto() {}
 };
 

+ 45 - 0
modules/mbedtls/crypto_mbedtls.cpp

@@ -317,3 +317,48 @@ PackedByteArray CryptoMbedTLS::generate_random_bytes(int p_bytes) {
 	mbedtls_ctr_drbg_random(&ctr_drbg, out.ptrw(), p_bytes);
 	return out;
 }
+
+mbedtls_md_type_t CryptoMbedTLS::_md_type_from_hashtype(HashingContext::HashType p_hash_type, int &r_size) {
+	switch (p_hash_type) {
+		case HashingContext::HASH_MD5:
+			r_size = 16;
+			return MBEDTLS_MD_MD5;
+		case HashingContext::HASH_SHA1:
+			r_size = 20;
+			return MBEDTLS_MD_SHA1;
+		case HashingContext::HASH_SHA256:
+			r_size = 32;
+			return MBEDTLS_MD_SHA256;
+		default:
+			r_size = 0;
+			ERR_FAIL_V_MSG(MBEDTLS_MD_NONE, "Invalid hash type.");
+	}
+}
+
+Vector<uint8_t> CryptoMbedTLS::sign(HashingContext::HashType p_hash_type, Vector<uint8_t> p_hash, Ref<CryptoKey> p_key) {
+	int size;
+	mbedtls_md_type_t type = _md_type_from_hashtype(p_hash_type, size);
+	ERR_FAIL_COND_V_MSG(type == MBEDTLS_MD_NONE, Vector<uint8_t>(), "Invalid hash type.");
+	ERR_FAIL_COND_V_MSG(p_hash.size() != size, Vector<uint8_t>(), "Invalid hash provided. Size must be " + itos(size));
+	Ref<CryptoKeyMbedTLS> key = static_cast<Ref<CryptoKeyMbedTLS>>(p_key);
+	ERR_FAIL_COND_V_MSG(!key.is_valid(), Vector<uint8_t>(), "Invalid key provided.");
+	ERR_FAIL_COND_V_MSG(key->is_public_only(), Vector<uint8_t>(), "Invalid key provided. Cannot sign with public_only keys.");
+	size_t sig_size = 0;
+	unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
+	Vector<uint8_t> out;
+	int ret = mbedtls_pk_sign(&(key->pkey), type, p_hash.ptr(), size, buf, &sig_size, mbedtls_ctr_drbg_random, &ctr_drbg);
+	ERR_FAIL_COND_V_MSG(ret, out, "Error while signing: " + itos(ret));
+	out.resize(sig_size);
+	copymem(out.ptrw(), buf, sig_size);
+	return out;
+}
+
+bool CryptoMbedTLS::verify(HashingContext::HashType p_hash_type, Vector<uint8_t> p_hash, Vector<uint8_t> p_signature, Ref<CryptoKey> p_key) {
+	int size;
+	mbedtls_md_type_t type = _md_type_from_hashtype(p_hash_type, size);
+	ERR_FAIL_COND_V_MSG(type == MBEDTLS_MD_NONE, false, "Invalid hash type.");
+	ERR_FAIL_COND_V_MSG(p_hash.size() != size, false, "Invalid hash provided. Size must be " + itos(size));
+	Ref<CryptoKeyMbedTLS> key = static_cast<Ref<CryptoKeyMbedTLS>>(p_key);
+	ERR_FAIL_COND_V_MSG(!key.is_valid(), false, "Invalid key provided.");
+	return mbedtls_pk_verify(&(key->pkey), type, p_hash.ptr(), size, p_signature.ptr(), p_signature.size()) == 0;
+}

+ 3 - 0
modules/mbedtls/crypto_mbedtls.h

@@ -106,6 +106,7 @@ private:
 	mbedtls_entropy_context entropy;
 	mbedtls_ctr_drbg_context ctr_drbg;
 	static X509CertificateMbedTLS *default_certs;
+	mbedtls_md_type_t _md_type_from_hashtype(HashingContext::HashType p_hash_type, int &r_size);
 
 public:
 	static Crypto *create();
@@ -117,6 +118,8 @@ public:
 	virtual PackedByteArray generate_random_bytes(int p_bytes);
 	virtual Ref<CryptoKey> generate_rsa(int p_bytes);
 	virtual Ref<X509Certificate> generate_self_signed_certificate(Ref<CryptoKey> p_key, String p_issuer_name, String p_not_before, String p_not_after);
+	virtual Vector<uint8_t> sign(HashingContext::HashType p_hash_type, Vector<uint8_t> p_hash, Ref<CryptoKey> p_key);
+	virtual bool verify(HashingContext::HashType p_hash_type, Vector<uint8_t> p_hash, Vector<uint8_t> p_signature, Ref<CryptoKey> p_key);
 
 	CryptoMbedTLS();
 	~CryptoMbedTLS();