// Attempt to load private key. bool AdbEndpoint::load_key() { BIO* bp_public; BIO* bp_private; wxFileName key_file_name(globalSettings()->settings_folder()); key_file_name.SetName("adb_public.pem"); bp_public = BIO_new_file(key_file_name.GetFullPath(), "r"); if (!bp_public) { wxLogError("Unable to open public key file %s", key_file_name.GetFullPath()); return false; } key_file_name.SetName("adb_private.pem"); bp_private = BIO_new_file(key_file_name.GetFullPath(), "r"); if (!bp_private) { wxLogError("Unable to open private key file %s", key_file_name.GetFullPath()); BIO_free_all(bp_public); return false; } _key = RSA_new(); PEM_read_bio_RSAPublicKey(bp_public, &_key, NULL, NULL); //PEM_read_bio_RSAPrivateKey(bp_private, &_key, NULL, NULL); BIO_free_all(bp_private); BIO_free_all(bp_public); return true; }
void RSATest() { RSA *key = NULL; BIO *bio_sec = NULL; BIO *bio_pub = NULL; FILE *fp_sec = NULL; FILE *fp_pub = NULL; fopen_s(&fp_sec, "sec.pem", "r"); fopen_s(&fp_pub, "pub.pem", "r"); bio_sec = BIO_new_fp(fp_sec, BIO_CLOSE); bio_pub = BIO_new_fp(fp_pub, BIO_CLOSE); if (!bio_sec || !bio_pub) { printf("f****d BIO_new_file\n"); return; } if (!PEM_read_bio_RSAPrivateKey(bio_sec, &key, NULL, "")) { printf("f****d PEM_read_bio_RSAPrivateKey\n"); return; } if (!PEM_read_bio_RSAPublicKey(bio_pub, &key, NULL, "")) { printf("f****d PEM_read_bio_RSAPublicKey\n"); return; } int len = RSA_size(key); unsigned char *buf = new unsigned char[len]; memset(buf, 0, len); if (-1 == RSA_private_encrypt(strlen(RSA_TEXT), (const unsigned char *)RSA_TEXT, buf, key, RSA_PKCS1_PADDING) ) { printf("f****d RSA_private_encrypt\n"); return; } OutputHexString(buf, len); printf("\n"); /* unsigned char *buf_test = new unsigned char[len]; memset(buf_test, 0, len); if (-1 == RSA_public_decrypt(len, buf, buf_test, key, RSA_PKCS1_PADDING) ) { printf("f****d RSA_public_decrypt\n"); return; } OutputHexString(buf_test, strlen(RSA_TEXT)); printf("\n"); delete [] buf_test; */ delete [] buf; BIO_free(bio_sec); }
int RSA_recup_key_pub ( unsigned char* key ) { // Déclaration variables BIO *keybio = NULL ; // On aloue notre object BIO avec la clé if ( ( keybio = BIO_new_mem_buf ( key, -1 ) ) == NULL ) { perror ( "Erreur_RSA_recup_key_pub : BIO_new_mem_buf() " ) ; fprintf ( stderr, "Code erreur OpenSSL : %lu \n ", ERR_get_error () ) ; return 0 ; } // On lie la clé à la structure RSA if ( ( frontale_key = PEM_read_bio_RSAPublicKey ( keybio, &frontale_key, NULL, NULL ) ) == NULL ) { perror ( "Erreur_RSA_recup_key_pub : PEM_read_bio_RSA_PUBKEY() " ) ; fprintf ( stderr, "Code erreur OpenSSL : %lu \n ", ERR_get_error () ) ; return 0 ; } // On free notre object BIO BIO_free ( keybio ) ; // On indique que tout s'est bien déroulé return 1 ; }
/** Read a PEM-encoded public key from the first <b>len</b> characters of * <b>src</b>, and store the result in <b>env</b>. Return 0 on success, -1 on * failure. */ int crypto_pk_read_public_key_from_string(crypto_pk_t *env, const char *src, size_t len) { BIO *b; // assert(env); // assert(src); // assert(len<INT_MAX); b = BIO_new(BIO_s_mem()); /* Create a memory BIO */ if (!b) return -1; BIO_write(b, src, (int)len); if (env->key) RSA_free(env->key); env->key = PEM_read_bio_RSAPublicKey(b, NULL, NULL, NULL); BIO_free(b); if (!env->key) { err(1, "reading public key from string"); return -1; } return 0; }
/* * rsa public decrypt */ char* rsa_decrypt_public(unsigned char *enc,int enc_len,char* private_key_str,int p_len,int *dec_len) { RSA* rsa; int rsa_len; char *p_de; #if 1 // private_key = rsa_key_seliaze(private_key_str); BIO* p_bio = BIO_new_mem_buf(private_key_str, -1); rsa = PEM_read_bio_RSAPublicKey(p_bio, NULL, 0, NULL); // if ( rsa == NULL ) { printf("RSA is NULL\n"); return NULL; } #else FILE* file=fopen("/tmp/r.key","r"); rsa=PEM_read_RSA_PUBKEY(file,NULL,NULL,NULL); #endif rsa_len=RSA_size(rsa); p_de=(unsigned char *)calloc(rsa_len+1,1); printf("rsa length = %d\n",rsa_len); int rc=0; rc = RSA_public_decrypt(rsa_len,(unsigned char *)enc,(unsigned char*)p_de,rsa,RSA_PKCS1_PADDING); //RSA_public_decrypt RSA_private_decrypt if ( rc<=0 ) { int e=ERR_get_error(); printf("error code is:%s\n",ERR_error_string(e,NULL)); return NULL; } RSA_free(rsa); printf("plain = %s\n",p_de); *dec_len = rc; return p_de; }
boolean an_key_get_public_key (uint8_t *key_label, an_key_t *key) { const char cert_filestr[] = PUBLIC_KEY_LOCATION; BIO *outbio = NULL; outbio = BIO_new_fp(stdout, BIO_NOCLOSE); int ret; char *pub_key = NULL; size_t pub_len; BIO* rsa_pub_bio = BIO_new_file(cert_filestr, "r"); RSA* rsa_pub = RSA_new(); ret = (PEM_read_bio_RSAPublicKey(rsa_pub_bio, &rsa_pub, NULL, NULL)!= NULL); if (ret == 0) { DEBUG_AN_LOG(AN_LOG_BS_EVENT, AN_DEBUG_INFO, NULL, "\n%sFailed to read public key from key pair",an_bs_event); return FALSE; } BIO *pub = BIO_new(BIO_s_mem()); PEM_write_bio_RSAPublicKey(pub, rsa_pub); pub_key = (char*)malloc(BN_num_bits(rsa_pub->n) + 1); pub_len = BN_num_bits(rsa_pub->n); BIO_read(pub, pub_key, pub_len); pub_key[pub_len] = '\0'; key->data = pub_key; key->len = pub_len; BIO_free(rsa_pub_bio); return TRUE; }
/* * rsa public key encrypt */ char* rsa_encrypt_public(unsigned char*txt,int txt_len,char* public_key_str,int p_len,int* enc_len) { //char *public_key = "-----BEGIN RSA PUBLIC KEY-----\nMIGJAoGBAL331YpDOljAJznk4eNt0TfZJREYypIhWTN/gx0g1iUIaLPlFR7ydjaB\npd9V7G3GvvOf3mGijP+9LjKdgQ8p1pgDW7DeXZk2dTAeQ4hdY287/sw6NFKJxMXA\nFGoUdARObVespCZBdHSqo8kFMAjVGge6ZoH6nAjGzvIfijgsj+2jAgMBAAE=\n-----END RSA PUBLIC KEY-----\n"; //char * private_key = "-----BEGIN RSA PRIVATE KEY-----\nMIICXQIBAAKBgQC999WKQzpYwCc55OHjbdE32SURGMqSIVkzf4MdINYlCGiz5RUe\n8nY2gaXfVextxr7zn95hooz/vS4ynYEPKdaYA1uw3l2ZNnUwHkOIXWNvO/7MOjRS\nicTFwBRqFHQETm1XrKQmQXR0qqPJBTAI1RoHumaB+pwIxs7yH4o4LI/towIDAQAB\nAoGBAI1ALF2EI2w+ZGxdzcBntXtLUI5n2qfReBwcogcUlWYv3Hp2yb+bFV7uA8IO\nh6AQeYd4xcffL+wwZJtqFb6Ko25XAei8Os3xjb9k5fCcyrmyY+5oeXdQHlcbd/f8\niy8/rOEHZTr4iBXe/8ADlQZlRUkYCblPZ4i4BgzBUB6HzhxhAkEA8wJRx/FjOo6F\noO1aTewbvFIv4Dckqq5j/pBu9fkv1AhMxSfdGnsYcuIn15Y1/RlnpxrmJNWgryvd\n+6LJGDgjWQJBAMgfoINe80YiPCdMoboMd/u1uf1BhwujbiJPSrS40lc3jfyPmHA4\n8hppo8QuELI4rXRE/im4c+zmyphxEyULpVsCQQDnD96JGin65MeE1AsYqpdYwmEJ\ndgVkUXt88wK+2ZizqMyubpAa/M6rdgTiRc7CASUAzF/myEYIKdLh0NAbOk3JAkAE\nxEQVfPh8bipSoU+k19EvzKdOcfYef9kKtirIXTKdYzRdlKoD2kdh+6wr6xD4vcLb\n5xzKr5sLRIAE24SiOEHLAkB1TBlvvvIltttSc9lOpq3UhmtHQJaS32lD2Lk2/zNx\nW6Jbsk+sCQXM0ww4GTCpHMISfokEPtqOPikPcVFs98Oj\n-----END RSA PRIVATE KEY-----\n"; RSA* rsa; int rsa_len; char *p_en; #if 1 //public_key = rsa_key_seliaze(public_key_str); BIO* p_bio = BIO_new_mem_buf(public_key_str, -1); printf("rsa_encrypt is %p \n",p_bio); rsa = PEM_read_bio_RSAPublicKey(p_bio, NULL, NULL, NULL); //PEM_read_bio_RSAPrivateKey if ( rsa == NULL ) { printf("RSA is NULL\n"); return NULL; } #else FILE* file=fopen("/tmp/r_pub.key","r"); rsa=PEM_read_RSAPrivateKey(file,NULL,NULL,NULL);//PEM_read_RSAPrivateKey #endif rsa_len=RSA_size(rsa); p_en=(unsigned char *)calloc(rsa_len+1,1); printf("rsa length = %d\n",rsa_len); int rc=0; if((rc=RSA_public_encrypt(txt_len,(unsigned char *)txt,(unsigned char*)p_en,rsa,RSA_PKCS1_PADDING))<=0) { int e=ERR_get_error(); printf("error code is:%s\n",ERR_error_string(e,NULL)); return NULL; } printf("rsa length = %d\n",strlen(p_en)); RSA_free(rsa); *enc_len = rc; return p_en; }
RSAKeyImpl::RSAKeyImpl( const std::string& publicKeyFile, const std::string& privateKeyFile, const std::string& privateKeyPassphrase): _pRSA(0) { poco_assert_dbg(_pRSA == 0); _pRSA = RSA_new(); if (!publicKeyFile.empty()) { BIO* bio = BIO_new(BIO_s_file()); if (!bio) throw Poco::IOException("Cannot create BIO for reading public key", publicKeyFile); int rc = BIO_read_filename(bio, publicKeyFile.c_str()); if (rc) { RSA* pubKey = PEM_read_bio_RSAPublicKey(bio, &_pRSA, 0, 0); BIO_free(bio); if (!pubKey) { freeRSA(); throw Poco::FileException("Failed to load public key", publicKeyFile); } } else { freeRSA(); throw Poco::FileNotFoundException("Public key file", publicKeyFile); } } if (!privateKeyFile.empty()) { BIO* bio = BIO_new(BIO_s_file()); if (!bio) throw Poco::IOException("Cannot create BIO for reading private key", privateKeyFile); int rc = BIO_read_filename(bio, privateKeyFile.c_str()); if (rc) { RSA* privKey = 0; if (privateKeyPassphrase.empty()) privKey = PEM_read_bio_RSAPrivateKey(bio, &_pRSA, 0, 0); else privKey = PEM_read_bio_RSAPrivateKey(bio, &_pRSA, 0, const_cast<char*>(privateKeyPassphrase.c_str())); BIO_free(bio); if (!privKey) { freeRSA(); throw Poco::FileException("Failed to load private key", privateKeyFile); } } else { freeRSA(); throw Poco::FileNotFoundException("Private key file", privateKeyFile); } } }
RSA* get_public_key_from_array(unsigned char* key){ RSA* rsa=NULL; BIO* keybio; keybio=BIO_new_mem_buf(key,-1); rsa=PEM_read_bio_RSAPublicKey(keybio,&rsa,NULL,NULL); if(rsa==NULL){ printf("\tError creating RSA public key\n"); } BIO_free_all(keybio); return rsa; }
RSAKeyImpl::RSAKeyImpl(std::istream* pPublicKeyStream, std::istream* pPrivateKeyStream, const std::string& privateKeyPassphrase): KeyPairImpl("rsa", KT_RSA_IMPL), _pRSA(0) { poco_assert_dbg(_pRSA == 0); _pRSA = RSA_new(); if (pPublicKeyStream) { std::string publicKeyData; Poco::StreamCopier::copyToString(*pPublicKeyStream, publicKeyData); BIO* bio = BIO_new_mem_buf(const_cast<char*>(publicKeyData.data()), static_cast<int>(publicKeyData.size())); if (!bio) throw Poco::IOException("Cannot create BIO for reading public key"); RSA* publicKey = PEM_read_bio_RSAPublicKey(bio, &_pRSA, 0, 0); if (!publicKey) { int rc = BIO_reset(bio); // BIO_reset() normally returns 1 for success and 0 or -1 for failure. // File BIOs are an exception, they return 0 for success and -1 for failure. if (rc != 1) throw Poco::FileException("Failed to load public key"); publicKey = PEM_read_bio_RSA_PUBKEY(bio, &_pRSA, 0, 0); } BIO_free(bio); if (!publicKey) { freeRSA(); throw Poco::FileException("Failed to load public key"); } } if (pPrivateKeyStream) { std::string privateKeyData; Poco::StreamCopier::copyToString(*pPrivateKeyStream, privateKeyData); BIO* bio = BIO_new_mem_buf(const_cast<char*>(privateKeyData.data()), static_cast<int>(privateKeyData.size())); if (!bio) throw Poco::IOException("Cannot create BIO for reading private key"); RSA* privateKey = 0; if (privateKeyPassphrase.empty()) privateKey = PEM_read_bio_RSAPrivateKey(bio, &_pRSA, 0, 0); else privateKey = PEM_read_bio_RSAPrivateKey(bio, &_pRSA, 0, const_cast<char*>(privateKeyPassphrase.c_str())); BIO_free(bio); if (!privateKey) { freeRSA(); throw Poco::FileException("Failed to load private key"); } } }
public_key::public_key( const bytes& d ) :my( std::make_shared<detail::pke_impl>() ) { string pem = "-----BEGIN RSA PUBLIC KEY-----\n"; auto b64 = fc::base64_encode( (const unsigned char*)d.data(), d.size() ); for( size_t i = 0; i < b64.size(); i += 64 ) pem += b64.substr( i, 64 ) + "\n"; pem += "-----END RSA PUBLIC KEY-----\n"; // fc::cerr<<pem; BIO* mem = (BIO*)BIO_new_mem_buf( (void*)pem.c_str(), pem.size() ); my->rsa = PEM_read_bio_RSAPublicKey(mem, NULL, NULL, NULL ); BIO_free(mem); }
/** * SHA1WithRSA公钥验签 * * LUA示例: * local codec = require('codec') * local src = 'something' * local sign = [[...]] --BASE64签名 * local bs = codec.base64_decode(sign) * local pem = [[...]] --公钥PEM字符串 * local type = 1 * local ok = codec.rsa_public_verify(src, bs, pem, type) --true/false */ static int codec_rsa_public_verify(lua_State *L) { size_t srclen, signlen; const char *src = luaL_checklstring(L, 1, &srclen); const char *sign = luaL_checklstring(L, 2, &signlen); char *pem = luaL_checkstring(L, 3); int type = luaL_checkint(L, 4); SHA_CTX ctx; int ctxlen = sizeof(ctx); unsigned char sha[SHA_DIGEST_LENGTH]; memset(sha, 0, SHA_DIGEST_LENGTH); if(SHA_Init(&ctx) != 1) { OPENSSL_cleanse(&ctx, ctxlen); return luaL_error(L, "SHA init error"); } if(SHA1_Update(&ctx, src, srclen) != 1) { OPENSSL_cleanse(&ctx, ctxlen); return luaL_error(L, "SHA update error"); } if(SHA1_Final(sha, &ctx) != 1) { OPENSSL_cleanse(&ctx, ctxlen); return luaL_error(L, "SHA update error"); } OPENSSL_cleanse(&ctx, ctxlen); BIO *bio = BIO_new_mem_buf((void *)pem, -1); if(bio == NULL) { BIO_free_all(bio); return luaL_error(L, "PEM error"); } RSA *rsa = type == 1 ? PEM_read_bio_RSAPublicKey(bio, NULL, NULL, NULL) : PEM_read_bio_RSA_PUBKEY(bio, NULL, NULL, NULL); if(rsa == NULL) { BIO_free_all(bio); return luaL_error(L, "RSA read public key error"); } BIO_free_all(bio); int ret = RSA_verify(NID_sha1, sha, SHA_DIGEST_LENGTH, (unsigned char *)sign, signlen, rsa); RSA_free(rsa); lua_pushboolean(L, ret); return 1; }
RSAKeyImpl::RSAKeyImpl(std::istream* pPublicKeyStream, std::istream* pPrivateKeyStream, const std::string& privateKeyPassphrase): _pRSA(0) { poco_assert_dbg(_pRSA == 0); _pRSA = RSA_new(); if (pPublicKeyStream) { std::string publicKeyData; Poco::StreamCopier::copyToString(*pPublicKeyStream, publicKeyData); BIO* bio = BIO_new_mem_buf(const_cast<char*>(publicKeyData.data()), static_cast<int>(publicKeyData.size())); if (!bio) throw Poco::IOException("Cannot create BIO for reading public key"); RSA* publicKey = PEM_read_bio_RSAPublicKey(bio, &_pRSA, 0, 0); if (!publicKey) { int rc = BIO_seek(bio, 0); if (rc != 0) throw Poco::FileException("Failed to load public key"); publicKey = PEM_read_bio_RSA_PUBKEY(bio, &_pRSA, 0, 0); } BIO_free(bio); if (!publicKey) { freeRSA(); throw Poco::FileException("Failed to load public key"); } } if (pPrivateKeyStream) { std::string privateKeyData; Poco::StreamCopier::copyToString(*pPrivateKeyStream, privateKeyData); BIO* bio = BIO_new_mem_buf(const_cast<char*>(privateKeyData.data()), static_cast<int>(privateKeyData.size())); if (!bio) throw Poco::IOException("Cannot create BIO for reading private key"); RSA* privateKey = 0; if (privateKeyPassphrase.empty()) privateKey = PEM_read_bio_RSAPrivateKey(bio, &_pRSA, 0, 0); else privateKey = PEM_read_bio_RSAPrivateKey(bio, &_pRSA, 0, const_cast<char*>(privateKeyPassphrase.c_str())); BIO_free(bio); if (!privateKey) { freeRSA(); throw Poco::FileException("Failed to load private key"); } } }
QByteArray JulyRSA::getSignature(QByteArray data, QByteArray keyArray) { BIO *bioKey = BIO_new(BIO_s_mem()); BIO_puts(bioKey,keyArray.data()); RSA *rsa=NULL; rsa=PEM_read_bio_RSAPublicKey(bioKey,&rsa,NULL,NULL); if(rsa==NULL) { BIO *errBIO = BIO_new(BIO_s_mem()); ERR_print_errors(errBIO); char *errData; long errSize=BIO_get_mem_data(errBIO, &errData); QByteArray errorString(errData,errSize); BIO_free(errBIO); BIO_free(bioKey); RSA_free(rsa); return QByteArray(); } int rsaSize=RSA_size(rsa); int dataLimit=rsaSize; QList<QByteArray> dataList; int curDataPos=0; while(curDataPos<data.size()) { int endPos=curDataPos+dataLimit-1; if(endPos>=data.size())endPos=data.size()-1; if(curDataPos<=endPos) dataList<<data.mid(curDataPos,endPos-curDataPos+1); else break; curDataPos=endPos+1; } QByteArray result; for(int n=0;n<dataList.count();n++) { unsigned char *finalData=(unsigned char *)malloc(rsaSize); int outSize=RSA_public_decrypt(dataList.at(n).size(), (unsigned char*)dataList.at(n).constData(), finalData, rsa, RSA_PKCS1_PADDING); result.append(QByteArray((char *)finalData,outSize)); free(finalData); } BIO_free(bioKey); RSA_free(rsa); return result; }
Result<RSA> RSA::from_pem(Slice pem) { init_crypto(); auto *bio = BIO_new_mem_buf(const_cast<void *>(static_cast<const void *>(pem.ubegin())), narrow_cast<int32>(pem.size())); if (bio == nullptr) { return Status::Error("Cannot create BIO"); } SCOPE_EXIT { BIO_free(bio); }; auto *rsa = RSA_new(); if (rsa == nullptr) { return Status::Error("Cannot create RSA"); } SCOPE_EXIT { RSA_free(rsa); }; if (!PEM_read_bio_RSAPublicKey(bio, &rsa, nullptr, nullptr)) { return Status::Error("Error while reading rsa pubkey"); } if (RSA_size(rsa) != 256) { return Status::Error("RSA_size != 256"); } const BIGNUM *n_num; const BIGNUM *e_num; #if OPENSSL_VERSION_NUMBER < 0x10100000L n_num = rsa->n; e_num = rsa->e; #else RSA_get0_key(rsa, &n_num, &e_num, nullptr); #endif auto n = static_cast<void *>(BN_dup(n_num)); auto e = static_cast<void *>(BN_dup(e_num)); if (n == nullptr || e == nullptr) { return Status::Error("Cannot dup BIGNUM"); } return RSA(BigNum::from_raw(n), BigNum::from_raw(e)); }
int COsslKey::setPublicKey( sqbind::CSqBinary *pBin ) {_STT(); Destroy(); if ( !pBin || !pBin->getUsed() ) return 0; m_pkey = EVP_PKEY_new(); if ( !m_pkey ) { oexERROR( 0, oexT( "EVP_PKEY_new() failed" ) ); Destroy(); return 0; } // end if BIO *pBio = BIO_new_mem_buf( pBin->_Ptr(), pBin->getUsed() ); if ( !pBio ) { oexERROR( 0, oexT( "BIO_new_mem_buf() failed" ) ); Destroy(); return 0; } // end if RSA *rsa = PEM_read_bio_RSAPublicKey( pBio, oexNULL, oexNULL, (void*)getPasswordPtr() ); if ( !rsa ) rsa = PEM_read_bio_RSA_PUBKEY( pBio, oexNULL, oexNULL, (void*)getPasswordPtr() ); if ( !rsa ) { const char *pErr = ERR_reason_error_string( ERR_get_error() ); oexERROR( 0, oexMks( oexT( "PEM_read_bio_RSAPublicKey(), PEM_read_bio_RSA_PUBKEY() failed : " ), pErr ? oexMbToStr( pErr ) : oexT( "Unknown" ) ) ); Destroy(); return 0; } // end if // Assign key if ( !EVP_PKEY_assign_RSA( m_pkey, rsa ) ) { oexERROR( 0, oexT( "EVP_PKEY_assign_RSA() failed" ) ); Destroy(); return 0; } // end if rsa = oexNULL; BIO_free( pBio ); return 1; }
int put_key_pem(int is_public_only, PyObject *py_key_pem, PyObject **py_private_key_ccn, PyObject **py_public_key_ccn, PyObject **py_public_key_digest) { unsigned char *key_pem; Py_ssize_t pem_len; RSA *key_rsa = NULL; BIO *bio = NULL; int r; unsigned long err; r = PyBytes_AsStringAndSize(py_key_pem, (char **) &key_pem, &pem_len); JUMP_IF_NEG(r, error); bio = BIO_new_mem_buf(key_pem, pem_len); JUMP_IF_NULL(bio, openssl_error); if (is_public_only) key_rsa = PEM_read_bio_RSAPublicKey(bio, NULL, NULL, NULL); else key_rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL); JUMP_IF_NULL(key_rsa, openssl_error); r = ccn_keypair_from_rsa(is_public_only, key_rsa, py_private_key_ccn, py_public_key_ccn); JUMP_IF_NEG(r, error); r = create_public_key_digest(key_rsa, py_public_key_digest, NULL); JUMP_IF_NEG(r, error); RSA_free(key_rsa); return 0; openssl_error: err = ERR_get_error(); PyErr_Format(g_PyExc_CCNKeyError, "Unable to parse key: %s", ERR_reason_error_string(err)); error: RSA_free(key_rsa); BIO_free(bio); return -1; }
static PyObject *load_key(PyObject *self, PyObject *args) { Py_buffer data; BIO *bio = NULL; RSA *rsa = NULL; RSAObject *result = NULL; #if PY_MAJOR_VERSION >= 3 if (!PyArg_ParseTuple(args, "y*:load_key", &data)) return NULL; #else if (!PyArg_ParseTuple(args, "s*:load_key", &data)) return NULL; #endif bio = BIO_new_mem_buf(data.buf, data.len); if (bio == NULL) { PyErr_SetString(PyExc_RuntimeError, "BIO_new_mem_buf"); goto cleanup; } if (PEM_read_bio_RSAPublicKey(bio, &rsa, NULL, NULL) == NULL) { PyErr_SetString(PyExc_ValueError, "invalid PKCS1 key"); goto cleanup; } result = PyObject_NEW(RSAObject, &RSAType); if (result == NULL) goto cleanup; result->rsa = rsa; rsa = NULL; cleanup: if (rsa) RSA_free(rsa); if (bio) BIO_free(bio); PyBuffer_Release(&data); return (PyObject *) result; }
/** * RSA公钥加密 * * LUA示例: * local codec = require('codec') * local src = 'something' * local pem = [[...]] --公钥PEM字符串 * local type = 1 * local bs = codec.rsa_public_encrypt(src, pem, type) * local dst = codec.base64_encode(bs) --BASE64密文 */ static int codec_rsa_public_encrypt(lua_State *L) { size_t len; const char *src = luaL_checklstring(L, 1, &len); char *pem = luaL_checkstring(L, 2); int type = luaL_checkint(L, 3); BIO *bio = BIO_new_mem_buf((void *)pem, -1); if(bio == NULL) { BIO_free_all(bio); return luaL_error(L, "PEM error"); } RSA *rsa = type == 1 ? PEM_read_bio_RSAPublicKey(bio, NULL, NULL, NULL) : PEM_read_bio_RSA_PUBKEY(bio, NULL, NULL, NULL); if(rsa == NULL) { BIO_free_all(bio); return luaL_error(L, "RSA read public key error"); } BIO_free_all(bio); int n = RSA_size(rsa); char dst[n]; memset(dst, 0, n); int ret = RSA_public_encrypt(len, (unsigned char *)src, (unsigned char *)dst, rsa, RSA_PKCS1_PADDING); if(ret != n) { RSA_free(rsa); BIO_free_all(bio); return luaL_error(L, "RSA public encrypt error"); } RSA_free(rsa); lua_pushlstring(L, dst, n); return 1; }
Private(base::const_byte_span key) : _rsa(PEM_read_bio_RSAPublicKey(BIO_new_mem_buf(const_cast<gsl::byte*>(key.data()), key.size()), 0, 0, 0)) { if (_rsa) { computeFingerprint(); } }
void PsUpdateDownloader::unpackUpdate() { QByteArray packed; if (!outputFile.open(QIODevice::ReadOnly)) { LOG(("Update Error: cant read updates file!")); return fatalFail(); } #ifdef Q_OS_WIN // use Lzma SDK for win const int32 hSigLen = 128, hShaLen = 20, hPropsLen = LZMA_PROPS_SIZE, hOriginalSizeLen = sizeof(int32), hSize = hSigLen + hShaLen + hPropsLen + hOriginalSizeLen; // header #else const int32 hSigLen = 128, hShaLen = 20, hPropsLen = 0, hOriginalSizeLen = sizeof(int32), hSize = hSigLen + hShaLen + hOriginalSizeLen; // header #endif QByteArray compressed = outputFile.readAll(); int32 compressedLen = compressed.size() - hSize; if (compressedLen <= 0) { LOG(("Update Error: bad compressed size: %1").arg(compressed.size())); return fatalFail(); } outputFile.close(); QString tempDirPath = cWorkingDir() + qsl("tupdates/temp"), readyDirPath = cWorkingDir() + qsl("tupdates/ready"); deleteDir(tempDirPath); deleteDir(readyDirPath); QDir tempDir(tempDirPath), readyDir(readyDirPath); if (tempDir.exists() || readyDir.exists()) { LOG(("Update Error: cant clear tupdates/temp or tupdates/ready dir!")); return fatalFail(); } uchar sha1Buffer[20]; bool goodSha1 = !memcmp(compressed.constData() + hSigLen, hashSha1(compressed.constData() + hSigLen + hShaLen, compressedLen + hPropsLen + hOriginalSizeLen, sha1Buffer), hShaLen); if (!goodSha1) { LOG(("Update Error: bad SHA1 hash of update file!")); return fatalFail(); } RSA *pbKey = PEM_read_bio_RSAPublicKey(BIO_new_mem_buf(const_cast<char*>(UpdatesPublicKey), -1), 0, 0, 0); if (!pbKey) { LOG(("Update Error: cant read public rsa key!")); return fatalFail(); } if (RSA_verify(NID_sha1, (const uchar*)(compressed.constData() + hSigLen), hShaLen, (const uchar*)(compressed.constData()), hSigLen, pbKey) != 1) { // verify signature RSA_free(pbKey); LOG(("Update Error: bad RSA signature of update file!")); return fatalFail(); } RSA_free(pbKey); QByteArray uncompressed; int32 uncompressedLen; memcpy(&uncompressedLen, compressed.constData() + hSigLen + hShaLen + hPropsLen, hOriginalSizeLen); uncompressed.resize(uncompressedLen); size_t resultLen = uncompressed.size(); #ifdef Q_OS_WIN // use Lzma SDK for win SizeT srcLen = compressedLen; int uncompressRes = LzmaUncompress((uchar*)uncompressed.data(), &resultLen, (const uchar*)(compressed.constData() + hSize), &srcLen, (const uchar*)(compressed.constData() + hSigLen + hShaLen), LZMA_PROPS_SIZE); if (uncompressRes != SZ_OK) { LOG(("Update Error: could not uncompress lzma, code: %1").arg(uncompressRes)); return fatalFail(); } #else lzma_stream stream = LZMA_STREAM_INIT; lzma_ret ret = lzma_stream_decoder(&stream, UINT64_MAX, LZMA_CONCATENATED); if (ret != LZMA_OK) { const char *msg; switch (ret) { case LZMA_MEM_ERROR: msg = "Memory allocation failed"; break; case LZMA_OPTIONS_ERROR: msg = "Specified preset is not supported"; break; case LZMA_UNSUPPORTED_CHECK: msg = "Specified integrity check is not supported"; break; default: msg = "Unknown error, possibly a bug"; break; } LOG(("Error initializing the decoder: %1 (error code %2)").arg(msg).arg(ret)); return fatalFail(); } stream.avail_in = compressedLen; stream.next_in = (uint8_t*)(compressed.constData() + hSize); stream.avail_out = resultLen; stream.next_out = (uint8_t*)uncompressed.data(); lzma_ret res = lzma_code(&stream, LZMA_FINISH); if (stream.avail_in) { LOG(("Error in decompression, %1 bytes left in _in of %2 whole.").arg(stream.avail_in).arg(compressedLen)); return fatalFail(); } else if (stream.avail_out) { LOG(("Error in decompression, %1 bytes free left in _out of %2 whole.").arg(stream.avail_out).arg(resultLen)); return fatalFail(); } lzma_end(&stream); if (res != LZMA_OK && res != LZMA_STREAM_END) { const char *msg; switch (res) { case LZMA_MEM_ERROR: msg = "Memory allocation failed"; break; case LZMA_FORMAT_ERROR: msg = "The input data is not in the .xz format"; break; case LZMA_OPTIONS_ERROR: msg = "Unsupported compression options"; break; case LZMA_DATA_ERROR: msg = "Compressed file is corrupt"; break; case LZMA_BUF_ERROR: msg = "Compressed data is truncated or otherwise corrupt"; break; default: msg = "Unknown error, possibly a bug"; break; } LOG(("Error in decompression: %1 (error code %2)").arg(msg).arg(res)); return fatalFail(); } #endif tempDir.mkdir(tempDir.absolutePath()); quint32 version; { QBuffer buffer(&uncompressed); buffer.open(QIODevice::ReadOnly); QDataStream stream(&buffer); stream.setVersion(QDataStream::Qt_5_1); stream >> version; if (stream.status() != QDataStream::Ok) { LOG(("Update Error: cant read version from downloaded stream, status: %1").arg(stream.status())); return fatalFail(); } if (version <= AppVersion) { LOG(("Update Error: downloaded version %1 is not greater, than mine %2").arg(version).arg(AppVersion)); return fatalFail(); } quint32 filesCount; stream >> filesCount; if (stream.status() != QDataStream::Ok) { LOG(("Update Error: cant read files count from downloaded stream, status: %1").arg(stream.status())); return fatalFail(); } if (!filesCount) { LOG(("Update Error: update is empty!")); return fatalFail(); } for (uint32 i = 0; i < filesCount; ++i) { QString relativeName; quint32 fileSize; QByteArray fileInnerData; bool executable = false; stream >> relativeName >> fileSize >> fileInnerData; #if defined Q_OS_MAC || defined Q_OS_LINUX stream >> executable; #endif if (stream.status() != QDataStream::Ok) { LOG(("Update Error: cant read file from downloaded stream, status: %1").arg(stream.status())); return fatalFail(); } if (fileSize != quint32(fileInnerData.size())) { LOG(("Update Error: bad file size %1 not matching data size %2").arg(fileSize).arg(fileInnerData.size())); return fatalFail(); } QFile f(tempDirPath + '/' + relativeName); if (!QDir().mkpath(QFileInfo(f).absolutePath())) { LOG(("Update Error: cant mkpath for file '%1'").arg(tempDirPath + '/' + relativeName)); return fatalFail(); } if (!f.open(QIODevice::WriteOnly)) { LOG(("Update Error: cant open file '%1' for writing").arg(tempDirPath + '/' + relativeName)); return fatalFail(); } if (f.write(fileInnerData) != fileSize) { f.close(); LOG(("Update Error: cant write file '%1'").arg(tempDirPath + '/' + relativeName)); return fatalFail(); } f.close(); if (executable) { QFileDevice::Permissions p = f.permissions(); p |= QFileDevice::ExeOwner | QFileDevice::ExeUser | QFileDevice::ExeGroup | QFileDevice::ExeOther; f.setPermissions(p); } } // create tdata/version file tempDir.mkdir(QDir(tempDirPath + qsl("/tdata")).absolutePath()); std::wstring versionString = ((version % 1000) ? QString("%1.%2.%3").arg(int(version / 1000000)).arg(int((version % 1000000) / 1000)).arg(int(version % 1000)) : QString("%1.%2").arg(int(version / 1000000)).arg(int((version % 1000000) / 1000))).toStdWString(); VerInt versionNum = VerInt(version), versionLen = VerInt(versionString.size() * sizeof(VerChar)); VerChar versionStr[32]; memcpy(versionStr, versionString.c_str(), versionLen); QFile fVersion(tempDirPath + qsl("/tdata/version")); if (!fVersion.open(QIODevice::WriteOnly)) { LOG(("Update Error: cant write version file '%1'").arg(tempDirPath + qsl("/version"))); return fatalFail(); } fVersion.write((const char*)&versionNum, sizeof(VerInt)); fVersion.write((const char*)&versionLen, sizeof(VerInt)); fVersion.write((const char*)&versionStr[0], versionLen); fVersion.close(); } if (!tempDir.rename(tempDir.absolutePath(), readyDir.absolutePath())) { LOG(("Update Error: cant rename temp dir '%1' to ready dir '%2'").arg(tempDir.absolutePath()).arg(readyDir.absolutePath())); return fatalFail(); } deleteDir(tempDirPath); outputFile.remove(); emit App::app()->updateReady(); }
CFMutableDictionaryRef SDMMD__CreatePairingMaterial(CFDataRef devicePubkey) { CFMutableDictionaryRef record = NULL; RSA *rsaBIOData = NULL; BIO *deviceBIO = SDMMD__create_bio_from_data(devicePubkey); if (deviceBIO) { PEM_read_bio_RSAPublicKey(deviceBIO, &rsaBIOData, NULL, NULL); BIO_free(deviceBIO); } else { printf("Could not decode device public key\\n"); } RSA *rootKeyPair = RSA_generate_key(2048, 65537, NULL, NULL); if (!rootKeyPair) { printf("Could not allocate root key pair\n"); } RSA *hostKeyPair = RSA_generate_key(2048, 65537, NULL, NULL); if (!hostKeyPair) { printf("Could not allocate host key pair\n"); } sdmmd_return_t result = kAMDSuccess; EVP_PKEY *rootEVP = EVP_PKEY_new(); if (!rootEVP) { printf("Could not allocate root EVP key\\n"); } else { result = EVP_PKEY_assign(rootEVP, EVP_CTRL_RAND_KEY, PtrCast(rootKeyPair, char *)); if (!result) { printf("Could not assign root key pair\n"); } } EVP_PKEY *hostEVP = EVP_PKEY_new(); if (!hostEVP) { printf("Could not allocate host EVP key\\n"); } else { result = EVP_PKEY_assign(hostEVP, EVP_CTRL_RAND_KEY, PtrCast(hostKeyPair, char *)); if (!result) { printf("Could not assign host key pair\n"); } } EVP_PKEY *deviceEVP = EVP_PKEY_new(); if (!deviceEVP) { printf("Could not allocate device EVP key\\n"); } else { result = EVP_PKEY_assign(deviceEVP, EVP_CTRL_RAND_KEY, PtrCast(rsaBIOData, char *)); if (!result) { printf("Could not assign device key pair\n"); } } X509 *rootX509 = X509_new(); if (!rootX509) { printf("Could not create root X509\\n"); } else { X509_set_pubkey(rootX509, rootEVP); X509_set_version(rootX509, 2); ASN1_INTEGER *rootSerial = X509_get_serialNumber(rootX509); ASN1_INTEGER_set(rootSerial, 0); ASN1_TIME *rootAsn1time = ASN1_TIME_new(); ASN1_TIME_set(rootAsn1time, 0); X509_set_notBefore(rootX509, rootAsn1time); ASN1_TIME_set(rootAsn1time, 0x12cc0300); // 60 sec * 60 minutes * 24 hours * 365 days * 10 years X509_set_notAfter(rootX509, rootAsn1time); ASN1_TIME_free(rootAsn1time); SDMMD__add_ext(rootX509, NID_basic_constraints, "critical,CA:TRUE"); SDMMD__add_ext(rootX509, NID_subject_key_identifier, "hash"); result = X509_sign(rootX509, rootEVP, EVP_sha1()); if (!result) { printf("Could not sign root cert\\n"); } } X509 *hostX509 = X509_new(); if (!hostX509) { printf("Could not create host X509\\n"); } else { X509_set_pubkey(hostX509, hostEVP); X509_set_version(hostX509, 2); ASN1_INTEGER *hostSerial = X509_get_serialNumber(hostX509); ASN1_INTEGER_set(hostSerial, 0); ASN1_TIME *hostAsn1time = ASN1_TIME_new(); ASN1_TIME_set(hostAsn1time, 0); X509_set_notBefore(hostX509, hostAsn1time); ASN1_TIME_set(hostAsn1time, 0x12cc0300); // 60 sec * 60 minutes * 24 hours * 365 days * 10 years X509_set_notAfter(hostX509, hostAsn1time); ASN1_TIME_free(hostAsn1time); SDMMD__add_ext(hostX509, NID_basic_constraints, "critical,CA:FALSE"); SDMMD__add_ext(hostX509, NID_subject_key_identifier, "hash"); SDMMD__add_ext(hostX509, NID_key_usage, "critical,digitalSignature,keyEncipherment"); result = X509_sign(hostX509, rootEVP, EVP_sha1()); if (!result) { printf("Could not sign host cert\\n"); } } X509 *deviceX509 = X509_new(); if (!deviceX509) { printf("Could not create device X509\\n"); } else { X509_set_pubkey(deviceX509, deviceEVP); X509_set_version(deviceX509, 2); ASN1_INTEGER *deviceSerial = X509_get_serialNumber(deviceX509); ASN1_INTEGER_set(deviceSerial, 0); ASN1_TIME *deviceAsn1time = ASN1_TIME_new(); ASN1_TIME_set(deviceAsn1time, 0); X509_set_notBefore(deviceX509, deviceAsn1time); ASN1_TIME_set(deviceAsn1time, 0x12cc0300); // 60 sec * 60 minutes * 24 hours * 365 days * 10 years X509_set_notAfter(deviceX509, deviceAsn1time); ASN1_TIME_free(deviceAsn1time); SDMMD__add_ext(deviceX509, NID_basic_constraints, "critical,CA:FALSE"); SDMMD__add_ext(deviceX509, NID_subject_key_identifier, "hash"); SDMMD__add_ext(deviceX509, NID_key_usage, "critical,digitalSignature,keyEncipherment"); result = X509_sign(deviceX509, rootEVP, EVP_sha1()); if (!result) { printf("Could not sign device cert\\n"); } } CFDataRef rootCert = SDMMD_CreateDataFromX509Certificate(rootX509); CFDataRef hostCert = SDMMD_CreateDataFromX509Certificate(hostX509); CFDataRef deviceCert = SDMMD_CreateDataFromX509Certificate(deviceX509); CFDataRef rootPrivKey = SDMMD_CreateDataFromPrivateKey(rootEVP); CFDataRef hostPrivKey = SDMMD_CreateDataFromPrivateKey(hostEVP); CFStringRef hostId = SDMMD_CreateUUID(); record = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if (record) { CFDictionarySetValue(record, CFSTR("RootCertificate"), rootCert); CFDictionarySetValue(record, CFSTR("HostCertificate"), hostCert); CFDictionarySetValue(record, CFSTR("DeviceCertificate"), deviceCert); CFDictionarySetValue(record, CFSTR("RootPrivateKey"), rootPrivKey); CFDictionarySetValue(record, CFSTR("HostPrivateKey"), hostPrivKey); CFDictionarySetValue(record, CFSTR("HostID"), hostId); } CFSafeRelease(rootCert); CFSafeRelease(hostCert); CFSafeRelease(deviceCert); CFSafeRelease(rootPrivKey); CFSafeRelease(hostPrivKey); CFSafeRelease(hostId); Safe(EVP_PKEY_free, rootEVP); Safe(EVP_PKEY_free, hostEVP); Safe(EVP_PKEY_free, deviceEVP); Safe(X509_free, rootX509); Safe(X509_free, hostX509); Safe(X509_free, deviceX509); return record; }
int main(int argc, char *argv[]) { QString workDir; #ifdef Q_OS_MAC if (QDir(QString()).absolutePath() == "/") { QString first = argc ? QString::fromLocal8Bit(argv[0]) : QString(); if (!first.isEmpty()) { QFileInfo info(first); if (info.exists()) { QDir result(info.absolutePath() + "/../../.."); workDir = result.absolutePath() + '/'; } } } #endif QString remove; int version = 0; QFileInfoList files; for (int i = 0; i < argc; ++i) { if (string("-path") == argv[i] && i + 1 < argc) { QString path = workDir + QString(argv[i + 1]); QFileInfo info(path); files.push_back(info); if (remove.isEmpty()) remove = info.canonicalPath() + "/"; } else if (string("-version") == argv[i] && i + 1 < argc) { version = QString(argv[i + 1]).toInt(); } else if (string("-dev") == argv[i]) { DevChannel = true; } else if (string("-beta") == argv[i] && i + 1 < argc) { BetaVersion = QString(argv[i + 1]).toULongLong(); if (BetaVersion > version * 1000ULL && BetaVersion < (version + 1) * 1000ULL) { DevChannel = false; BetaSignature = countBetaVersionSignature(BetaVersion); if (BetaSignature.isEmpty()) { return -1; } } else { cout << "Bad -beta param value passed, should be for the same version: " << version << ", beta: " << BetaVersion << "\n"; return -1; } } } if (files.isEmpty() || remove.isEmpty() || version <= 1016 || version > 999999999) { #ifdef Q_OS_WIN cout << "Usage: Packer.exe -path {file} -version {version} OR Packer.exe -path {dir} -version {version}\n"; #elif defined Q_OS_MAC cout << "Usage: Packer.app -path {file} -version {version} OR Packer.app -path {dir} -version {version}\n"; #else cout << "Usage: Packer -path {file} -version {version} OR Packer -path {dir} -version {version}\n"; #endif return -1; } bool hasDirs = true; while (hasDirs) { hasDirs = false; for (QFileInfoList::iterator i = files.begin(); i != files.end(); ++i) { QFileInfo info(*i); QString fullPath = info.canonicalFilePath(); if (info.isDir()) { hasDirs = true; files.erase(i); QDir d = QDir(info.absoluteFilePath()); QString fullDir = d.canonicalPath(); QStringList entries = d.entryList(QDir::Files | QDir::Dirs | QDir::NoSymLinks | QDir::NoDotAndDotDot); files.append(d.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoSymLinks | QDir::NoDotAndDotDot)); break; } else if (!info.isReadable()) { cout << "Can't read: " << info.absoluteFilePath().toUtf8().constData() << "\n"; return -1; } else if (info.isHidden()) { hasDirs = true; files.erase(i); break; } } } for (QFileInfoList::iterator i = files.begin(); i != files.end(); ++i) { QFileInfo info(*i); if (!info.canonicalFilePath().startsWith(remove)) { cout << "Can't find '" << remove.toUtf8().constData() << "' in file '" << info.canonicalFilePath().toUtf8().constData() << "' :(\n"; return -1; } } QByteArray result; { QBuffer buffer(&result); buffer.open(QIODevice::WriteOnly); QDataStream stream(&buffer); stream.setVersion(QDataStream::Qt_5_1); if (BetaVersion) { stream << quint32(0x7FFFFFFF); stream << quint64(BetaVersion); } else { stream << quint32(version); } stream << quint32(files.size()); cout << "Found " << files.size() << " file" << (files.size() == 1 ? "" : "s") << "..\n"; for (QFileInfoList::iterator i = files.begin(); i != files.end(); ++i) { QFileInfo info(*i); QString fullName = info.canonicalFilePath(); QString name = fullName.mid(remove.length()); cout << name.toUtf8().constData() << " (" << info.size() << ")\n"; QFile f(fullName); if (!f.open(QIODevice::ReadOnly)) { cout << "Can't open '" << fullName.toUtf8().constData() << "' for read..\n"; return -1; } QByteArray inner = f.readAll(); stream << name << quint32(inner.size()) << inner; #if defined Q_OS_MAC || defined Q_OS_LINUX stream << (QFileInfo(fullName).isExecutable() ? true : false); #endif } if (stream.status() != QDataStream::Ok) { cout << "Stream status is bad: " << stream.status() << "\n"; return -1; } } int32 resultSize = result.size(); cout << "Compression start, size: " << resultSize << "\n"; QByteArray compressed, resultCheck; #ifdef Q_OS_WIN // use Lzma SDK for win const int32 hSigLen = 128, hShaLen = 20, hPropsLen = LZMA_PROPS_SIZE, hOriginalSizeLen = sizeof(int32), hSize = hSigLen + hShaLen + hPropsLen + hOriginalSizeLen; // header compressed.resize(hSize + resultSize + 1024 * 1024); // rsa signature + sha1 + lzma props + max compressed size size_t compressedLen = compressed.size() - hSize; size_t outPropsSize = LZMA_PROPS_SIZE; uchar *_dest = (uchar*)(compressed.data() + hSize); size_t *_destLen = &compressedLen; const uchar *_src = (const uchar*)(result.constData()); size_t _srcLen = result.size(); uchar *_outProps = (uchar*)(compressed.data() + hSigLen + hShaLen); int res = LzmaCompress(_dest, _destLen, _src, _srcLen, _outProps, &outPropsSize, 9, 64 * 1024 * 1024, 4, 0, 2, 273, 2); if (res != SZ_OK) { cout << "Error in compression: " << res << "\n"; return -1; } compressed.resize(int(hSize + compressedLen)); memcpy(compressed.data() + hSigLen + hShaLen + hPropsLen, &resultSize, hOriginalSizeLen); cout << "Compressed to size: " << compressedLen << "\n"; cout << "Checking uncompressed..\n"; int32 resultCheckLen; memcpy(&resultCheckLen, compressed.constData() + hSigLen + hShaLen + hPropsLen, hOriginalSizeLen); if (resultCheckLen <= 0 || resultCheckLen > 1024 * 1024 * 1024) { cout << "Bad result len: " << resultCheckLen << "\n"; return -1; } resultCheck.resize(resultCheckLen); size_t resultLen = resultCheck.size(); SizeT srcLen = compressedLen; int uncompressRes = LzmaUncompress((uchar*)resultCheck.data(), &resultLen, (const uchar*)(compressed.constData() + hSize), &srcLen, (const uchar*)(compressed.constData() + hSigLen + hShaLen), LZMA_PROPS_SIZE); if (uncompressRes != SZ_OK) { cout << "Uncompress failed: " << uncompressRes << "\n"; return -1; } if (resultLen != size_t(result.size())) { cout << "Uncompress bad size: " << resultLen << ", was: " << result.size() << "\n"; return -1; } #else // use liblzma for others const int32 hSigLen = 128, hShaLen = 20, hPropsLen = 0, hOriginalSizeLen = sizeof(int32), hSize = hSigLen + hShaLen + hOriginalSizeLen; // header compressed.resize(hSize + resultSize + 1024 * 1024); // rsa signature + sha1 + lzma props + max compressed size size_t compressedLen = compressed.size() - hSize; lzma_stream stream = LZMA_STREAM_INIT; int preset = 9 | LZMA_PRESET_EXTREME; lzma_ret ret = lzma_easy_encoder(&stream, preset, LZMA_CHECK_CRC64); if (ret != LZMA_OK) { const char *msg; switch (ret) { case LZMA_MEM_ERROR: msg = "Memory allocation failed"; break; case LZMA_OPTIONS_ERROR: msg = "Specified preset is not supported"; break; case LZMA_UNSUPPORTED_CHECK: msg = "Specified integrity check is not supported"; break; default: msg = "Unknown error, possibly a bug"; break; } cout << "Error initializing the encoder: " << msg << " (error code " << ret << ")\n"; return -1; } stream.avail_in = resultSize; stream.next_in = (uint8_t*)result.constData(); stream.avail_out = compressedLen; stream.next_out = (uint8_t*)(compressed.data() + hSize); lzma_ret res = lzma_code(&stream, LZMA_FINISH); compressedLen -= stream.avail_out; lzma_end(&stream); if (res != LZMA_OK && res != LZMA_STREAM_END) { const char *msg; switch (res) { case LZMA_MEM_ERROR: msg = "Memory allocation failed"; break; case LZMA_DATA_ERROR: msg = "File size limits exceeded"; break; default: msg = "Unknown error, possibly a bug"; break; } cout << "Error in compression: " << msg << " (error code " << res << ")\n"; return -1; } compressed.resize(int(hSize + compressedLen)); memcpy(compressed.data() + hSigLen + hShaLen, &resultSize, hOriginalSizeLen); cout << "Compressed to size: " << compressedLen << "\n"; cout << "Checking uncompressed..\n"; int32 resultCheckLen; memcpy(&resultCheckLen, compressed.constData() + hSigLen + hShaLen, hOriginalSizeLen); if (resultCheckLen <= 0 || resultCheckLen > 1024 * 1024 * 1024) { cout << "Bad result len: " << resultCheckLen << "\n"; return -1; } resultCheck.resize(resultCheckLen); size_t resultLen = resultCheck.size(); stream = LZMA_STREAM_INIT; ret = lzma_stream_decoder(&stream, UINT64_MAX, LZMA_CONCATENATED); if (ret != LZMA_OK) { const char *msg; switch (ret) { case LZMA_MEM_ERROR: msg = "Memory allocation failed"; break; case LZMA_OPTIONS_ERROR: msg = "Specified preset is not supported"; break; case LZMA_UNSUPPORTED_CHECK: msg = "Specified integrity check is not supported"; break; default: msg = "Unknown error, possibly a bug"; break; } cout << "Error initializing the decoder: " << msg << " (error code " << ret << ")\n"; return -1; } stream.avail_in = compressedLen; stream.next_in = (uint8_t*)(compressed.constData() + hSize); stream.avail_out = resultLen; stream.next_out = (uint8_t*)resultCheck.data(); res = lzma_code(&stream, LZMA_FINISH); if (stream.avail_in) { cout << "Error in decompression, " << stream.avail_in << " bytes left in _in of " << compressedLen << " whole.\n"; return -1; } else if (stream.avail_out) { cout << "Error in decompression, " << stream.avail_out << " bytes free left in _out of " << resultLen << " whole.\n"; return -1; } lzma_end(&stream); if (res != LZMA_OK && res != LZMA_STREAM_END) { const char *msg; switch (res) { case LZMA_MEM_ERROR: msg = "Memory allocation failed"; break; case LZMA_FORMAT_ERROR: msg = "The input data is not in the .xz format"; break; case LZMA_OPTIONS_ERROR: msg = "Unsupported compression options"; break; case LZMA_DATA_ERROR: msg = "Compressed file is corrupt"; break; case LZMA_BUF_ERROR: msg = "Compressed data is truncated or otherwise corrupt"; break; default: msg = "Unknown error, possibly a bug"; break; } cout << "Error in decompression: " << msg << " (error code " << res << ")\n"; return -1; } #endif if (memcmp(result.constData(), resultCheck.constData(), resultLen)) { cout << "Data differ :(\n"; return -1; } /**/ result = resultCheck = QByteArray(); cout << "Counting SHA1 hash..\n"; uchar sha1Buffer[20]; memcpy(compressed.data() + hSigLen, hashSha1(compressed.constData() + hSigLen + hShaLen, uint32(compressedLen + hPropsLen + hOriginalSizeLen), sha1Buffer), hShaLen); // count sha1 uint32 siglen = 0; cout << "Signing..\n"; RSA *prKey = PEM_read_bio_RSAPrivateKey(BIO_new_mem_buf(const_cast<char*>((DevChannel || BetaVersion) ? PrivateDevKey : PrivateKey), -1), 0, 0, 0); if (!prKey) { cout << "Could not read RSA private key!\n"; return -1; } if (RSA_size(prKey) != hSigLen) { cout << "Bad private key, size: " << RSA_size(prKey) << "\n"; RSA_free(prKey); return -1; } if (RSA_sign(NID_sha1, (const uchar*)(compressed.constData() + hSigLen), hShaLen, (uchar*)(compressed.data()), &siglen, prKey) != 1) { // count signature cout << "Signing failed!\n"; RSA_free(prKey); return -1; } RSA_free(prKey); if (siglen != hSigLen) { cout << "Bad signature length: " << siglen << "\n"; return -1; } cout << "Checking signature..\n"; RSA *pbKey = PEM_read_bio_RSAPublicKey(BIO_new_mem_buf(const_cast<char*>((DevChannel || BetaVersion) ? PublicDevKey : PublicKey), -1), 0, 0, 0); if (!pbKey) { cout << "Could not read RSA public key!\n"; return -1; } if (RSA_verify(NID_sha1, (const uchar*)(compressed.constData() + hSigLen), hShaLen, (const uchar*)(compressed.constData()), siglen, pbKey) != 1) { // verify signature RSA_free(pbKey); cout << "Signature verification failed!\n"; return -1; } cout << "Signature verified!\n"; RSA_free(pbKey); #ifdef Q_OS_WIN QString outName(QString("tupdate%1").arg(BetaVersion ? BetaVersion : version)); #elif defined Q_OS_MAC QString outName(QString("tmacupd%1").arg(BetaVersion ? BetaVersion : version)); #elif defined Q_OS_LINUX32 QString outName(QString("tlinux32upd%1").arg(BetaVersion ? BetaVersion : version)); #elif defined Q_OS_LINUX64 QString outName(QString("tlinuxupd%1").arg(BetaVersion ? BetaVersion : version)); #else #error Unknown platform! #endif if (BetaVersion) { outName += "_" + BetaSignature; } QFile out(outName); if (!out.open(QIODevice::WriteOnly)) { cout << "Can't open '" << outName.toUtf8().constData() << "' for write..\n"; return -1; } out.write(compressed); out.close(); if (BetaVersion) { QString keyName(QString("tbeta_%1_key").arg(BetaVersion)); QFile key(keyName); if (!key.open(QIODevice::WriteOnly)) { cout << "Can't open '" << keyName.toUtf8().constData() << "' for write..\n"; return -1; } key.write(BetaSignature.toUtf8()); key.close(); } cout << "Update file '" << outName.toUtf8().constData() << "' written successfully!\n"; return 0; }
Impl(const char *key) : rsa(PEM_read_bio_RSAPublicKey(BIO_new_mem_buf(const_cast<char*>(key), -1), 0, 0, 0)) { }
int main() { BIO *bio; RSA *rsa=0, *rsa_pub, *rsa_priv=0; char buf[4096], enc[4096], dec[4096]; BUF_MEM *ptr; int len, enc_len, dec_len; int i; BF_KEY key; char ivec_orig[8] = {1, 2, 3, 4, 5, 6, 7, 8}, ivec[8]; do { //OpenSSL_add_all_algorithms(); //OpenSSL_add_all_ciphers(); //OpenSSL_add_all_digests(); printf("generate_key:\n"); rsa = RSA_generate_key(1024, 3, gen_cb, 0); printf("\n"); printf("pem public key:\n"); bio = BIO_new(BIO_s_mem()); i = PEM_write_bio_RSAPublicKey(bio, rsa); BIO_flush(bio); i = BIO_get_mem_ptr(bio, &ptr); printf("pem public key len=%d\n", ptr->length); fwrite(ptr->data, ptr->length, 1, stdout); len = ptr->length; memcpy(buf, ptr->data, len); BIO_free(bio); printf("\n"); bio = BIO_new_mem_buf(buf, len); rsa_pub = PEM_read_bio_RSAPublicKey(bio, 0, 0, 0); BIO_free(bio); printf("pem private key:\n"); bio = BIO_new(BIO_s_mem()); i = PEM_write_bio_RSAPrivateKey(bio, rsa, 0, 0, 0, 0, 0); BIO_flush(bio); i = BIO_get_mem_ptr(bio, &ptr); printf("pem private key i=%d len=%d\n", i, ptr->length); fwrite(ptr->data, ptr->length, 1, stdout); len = ptr->length; memcpy(buf, ptr->data, len); BIO_free(bio); printf("\n"); bio = BIO_new_mem_buf(buf, len); rsa_priv = PEM_read_bio_RSAPrivateKey(bio, 0, 0, 0); BIO_free(bio); /* encrypt */ printf("buffer:\n"); len = sprintf(buf, "1234567890123456"); len = 128/8; RAND_bytes(buf, len); printf("buf_len=%d\n", len); //printf("%s", dec); for(i=0; i<len; i++) { printf("%02x", (unsigned int)buf[i]&0xff); } printf("\n"); printf("public_encrypt:\n"); memset(enc, 0, sizeof(enc)); enc_len = RSA_public_encrypt(len, buf, enc, rsa_pub, RSA_PKCS1_OAEP_PADDING); if( enc_len < 0 ) { printf("err=%ld\n", ERR_get_error()); break; } printf("enc_len=%d\n", enc_len); for(i=0; i<enc_len; i++) { printf("%02x", (unsigned int)enc[i]&0xff); } printf("\n"); printf("public_decrypt:\n"); memset(dec, 0, sizeof(dec)); dec_len = RSA_private_decrypt(enc_len, enc, dec, rsa_priv, RSA_PKCS1_OAEP_PADDING); if( dec_len < 0 ) { printf("err=%ld\n", ERR_get_error()); break; } printf("dec_len=%d\n", dec_len); for(i=0; i<dec_len; i++) { printf("%02x", (unsigned int)dec[i]&0xff); } printf("\n"); // blowfish BF_set_key(&key, dec_len, dec); i = 0; memcpy(ivec, ivec_orig, 8); memset(buf, 0, sizeof(buf)); BF_cfb64_encrypt(enc, buf, enc_len, &key, ivec, &i, BF_ENCRYPT); printf("BF_cfb64_encrypt:\n"); for(i=0; i<enc_len; i++) { printf("%02x", (unsigned int)buf[i]&0xff); } printf("\n"); i = 0; memcpy(ivec, ivec_orig, 8); memset(enc, 0, sizeof(buf)); BF_cfb64_encrypt(buf, enc, enc_len, &key, ivec, &i, BF_DECRYPT); printf("BF_cfb64_decrypt:\n"); for(i=0; i<enc_len; i++) { printf("%02x", (unsigned int)enc[i]&0xff); } printf("\n"); } while(0); if( rsa ) { RSA_free(rsa); } return 0; }
static int openssl_pkey_read(lua_State*L) { EVP_PKEY * key = NULL; BIO* in = load_bio_object(L, 1); int priv = lua_isnoneornil(L, 2) ? 0 : auxiliar_checkboolean(L, 2); int fmt = luaL_checkoption(L, 3, "auto", format); const char* passphrase = luaL_optstring(L, 4, NULL); int type = -1; if (passphrase) { if (strcmp(passphrase, "rsa") == 0 || strcmp(passphrase, "RSA") == 0) type = EVP_PKEY_RSA; else if (strcmp(passphrase, "dsa") == 0 || strcmp(passphrase, "DSA") == 0) type = EVP_PKEY_DSA; else if (strcmp(passphrase, "ec") == 0 || strcmp(passphrase, "EC") == 0) type = EVP_PKEY_EC; } if (fmt == FORMAT_AUTO) { fmt = bio_is_der(in) ? FORMAT_DER : FORMAT_PEM; } if (!priv) { if (fmt == FORMAT_PEM) { key = PEM_read_bio_PUBKEY(in, NULL, NULL, (void*)passphrase); BIO_reset(in); if (key == NULL && type == EVP_PKEY_RSA) { RSA* rsa = PEM_read_bio_RSAPublicKey(in, NULL, NULL, NULL); if (rsa) { key = EVP_PKEY_new(); EVP_PKEY_assign_RSA(key, rsa); } } }else if (fmt == FORMAT_DER) { key = d2i_PUBKEY_bio(in, NULL); BIO_reset(in); if (!key && type!=-1) { char * bio_mem_ptr; long bio_mem_len; bio_mem_len = BIO_get_mem_data(in, &bio_mem_ptr); key = d2i_PublicKey(type, NULL, (const unsigned char **)&bio_mem_ptr, bio_mem_len); BIO_reset(in); } } } else { if (fmt == FORMAT_PEM) { key = PEM_read_bio_PrivateKey(in, NULL, NULL, (void*)passphrase); BIO_reset(in); }else if (fmt == FORMAT_DER) { if (passphrase) key = d2i_PKCS8PrivateKey_bio(in, NULL, NULL, (void*)passphrase); else key = d2i_PrivateKey_bio(in, NULL); BIO_reset(in); if (!key && type != -1) { char * bio_mem_ptr; long bio_mem_len; bio_mem_len = BIO_get_mem_data(in, &bio_mem_ptr); key = d2i_PrivateKey(type, NULL, (const unsigned char **)&bio_mem_ptr, bio_mem_len); BIO_reset(in); } } } BIO_free(in); if (key) { PUSH_OBJECT(key, "openssl.evp_pkey"); return 1; } return openssl_pushresult(L, 0); }
int validate_token(bstring token) { int i; OpenSSL_add_all_algorithms(); struct bstrList *parts = bsplit(token, '|'); dictionary *dict = dictionary_new(10); bstring sig = bfromcstr("sig"); bstring to_sign = bfromcstr(""); for (i = 0; i < parts->qty; i++) { printf("%d: %s\n", i, parts->entry[i]->data); struct bstrList *x = bsplit(parts->entry[i], '='); if (x->qty == 2) { if (bstrcmp(x->entry[0], sig) != 0) { if (blength(to_sign) > 0) bconchar(to_sign, '|'); bconcat(to_sign, parts->entry[i]); } dictionary_set(dict, bdata(x->entry[0]), bdata(x->entry[1])); } bstrListDestroy(x); } bstrListDestroy(parts); parts = 0; bdestroy(sig); dictionary_dump(dict, stdout); printf("to sign: '%s'\n", bdata(to_sign)); // Check signing subject (need to know the valid values) char *subj = dictionary_get(dict, "SigningSubject", 0); if (!subj) { fprintf(stderr, "could not get signing subject\n"); return 0; } char *sigstr = dictionary_get(dict, "sig", 0); printf("sig to verify is %s\n", sigstr); bstring binsig = bfromcstralloc(strlen(sigstr) / 2, ""); char *s, *e; for (s = sigstr, e = sigstr + strlen(sigstr); s < e; s += 2) { char n[3]; n[0] = s[0]; n[1] = s[1]; n[2] = 0; long int v = strtol(n, 0, 16); // printf("n=%s v=%ld %lx\n", n, v, v); bconchar(binsig, (char) v); } unsigned char *sha = SHA1((const unsigned char *) to_sign->data, to_sign->slen, 0); bdestroy(to_sign); bstring bsubj = bfromcstr(subj); bstring pubkey = get_signer_pubkey(bsubj); BIO *bio = BIO_new(BIO_s_mem()); BIO_puts(bio, bdata(pubkey)); RSA *rsa = PEM_read_bio_RSAPublicKey(bio, 0, 0, 0); int rc = RSA_verify(NID_sha1, sha, SHA_DIGEST_LENGTH, binsig->data, binsig->slen, rsa); printf("rc=%d\n", rc); bdestroy(bsubj); bdestroy(binsig); bdestroy(pubkey); BIO_free(bio); RSA_free(rsa); dictionary_del(dict); EVP_cleanup(); return rc; }
RSAKeyImpl::RSAKeyImpl(const std::string& publicKeyFile, const std::string& privateKeyFile, const std::string& privateKeyPassphrase): KeyPairImpl("rsa", KT_RSA_IMPL), _pRSA(0) { poco_assert_dbg(_pRSA == 0); _pRSA = RSA_new(); if (!publicKeyFile.empty()) { BIO* bio = BIO_new(BIO_s_file()); if (!bio) throw Poco::IOException("Cannot create BIO for reading public key", publicKeyFile); int rc = BIO_read_filename(bio, publicKeyFile.c_str()); if (rc) { RSA* pubKey = PEM_read_bio_RSAPublicKey(bio, &_pRSA, 0, 0); if (!pubKey) { int rc = BIO_reset(bio); // BIO_reset() normally returns 1 for success and 0 or -1 for failure. // File BIOs are an exception, they return 0 for success and -1 for failure. if (rc != 0) throw Poco::FileException("Failed to load public key", publicKeyFile); pubKey = PEM_read_bio_RSA_PUBKEY(bio, &_pRSA, 0, 0); } BIO_free(bio); if (!pubKey) { freeRSA(); throw Poco::FileException("Failed to load public key", publicKeyFile); } } else { freeRSA(); throw Poco::FileNotFoundException("Public key file", publicKeyFile); } } if (!privateKeyFile.empty()) { BIO* bio = BIO_new(BIO_s_file()); if (!bio) throw Poco::IOException("Cannot create BIO for reading private key", privateKeyFile); int rc = BIO_read_filename(bio, privateKeyFile.c_str()); if (rc) { RSA* privKey = 0; if (privateKeyPassphrase.empty()) privKey = PEM_read_bio_RSAPrivateKey(bio, &_pRSA, 0, 0); else privKey = PEM_read_bio_RSAPrivateKey(bio, &_pRSA, 0, const_cast<char*>(privateKeyPassphrase.c_str())); BIO_free(bio); if (!privKey) { freeRSA(); throw Poco::FileException("Failed to load private key", privateKeyFile); } } else { freeRSA(); throw Poco::FileNotFoundException("Private key file", privateKeyFile); } } }
void SecureServer::generateCertificate(const std::string& publicKey, const std::string& privateKey, const std::string& password, const long& secsValid, const std::vector<std::pair<std::string,std::string> >& x509Entries, const std::string& x509Filename) throw (boost::system::system_error) { std::cerr << "generating certificate" << std::endl; std::unique_ptr<X509,void (*)(X509*)> x509(X509_new(), &X509_free); if(ASN1_INTEGER_set(X509_get_serialNumber(x509.get()), std::time(nullptr)) != 1){ throw_system_error_ssl("Could not set X509 parameters"); } X509_gmtime_adj(X509_get_notBefore(x509.get()), 0); X509_gmtime_adj(X509_get_notAfter(x509.get()), secsValid); std::unique_ptr<EVP_PKEY,void(*)(EVP_PKEY*)> privKey(EVP_PKEY_new(), &EVP_PKEY_free); std::unique_ptr<EVP_PKEY,void(*)(EVP_PKEY*)> pubKey(EVP_PKEY_new(), &EVP_PKEY_free); std::unique_ptr<BIO,void (*)(BIO*)> privateBIO(BIO_new_file(privateKey.c_str(), "r"), &BIO_free_all); if(!privateBIO){ throw_system_error_ssl("Could not open "+privateKey+" for reading"); } pem_password_cb* password_cb(nullptr); void *password_u(nullptr); if(!password.empty()){ password_cb = &pemPasswordCBFromString; password_u = (void*)&password; } std::unique_ptr<RSA,void(*)(RSA*)> rsa(PEM_read_bio_RSAPrivateKey(privateBIO.get(), nullptr, password_cb, password_u),&RSA_free); if(!rsa){ throw_system_error_ssl("Could not read PEM RSA private key from "+privateKey); } std::cerr << "read " << privateKey << std::endl; if(EVP_PKEY_set1_RSA(privKey.get(), rsa.get()) != 1){ throw_system_error_ssl("Could not assign EVP_PKEY from RSA private key"); } std::cerr << "assigned EVP_PKEY" << std::endl; std::unique_ptr<BIO,void (*)(BIO*)> publicBIO(BIO_new_file(publicKey.c_str(), "r"), &BIO_free_all); if(!publicBIO){ throw_system_error_ssl("Could not open "+publicKey+" for reading"); } RSA *ptr = rsa.get(); if(PEM_read_bio_RSAPublicKey(publicBIO.get(),&ptr,nullptr,nullptr) == nullptr){ throw_system_error_ssl("Could not read PEM RSA public key from "+publicKey); } std::cerr << "read " << publicKey << std::endl; if(EVP_PKEY_set1_RSA(pubKey.get(), rsa.get()) != 1){ throw_system_error_ssl("Could not assign EVP_PKEY from RSA public key"); } if(X509_set_pubkey(x509.get(), pubKey.get()) != 1){ throw_system_error_ssl("Could nost assign X509 public key from EVP_PKEY"); } X509_NAME *name = X509_get_subject_name(x509.get()); std::cerr << "got subject name" << std::endl; for(const std::pair<std::string,std::string>& entry : x509Entries){ if(X509_NAME_add_entry_by_txt(name, entry.first.c_str(), MBSTRING_ASC, (const unsigned char*)entry.second.c_str(), entry.second.length(), -1, 0) != 1){ throw_system_error_ssl("Could not add X509 entry /"+entry.first+"/ = \""+entry.second+'"'); } std::cerr << "added entry /" << entry.first << "/ = \"" << entry.second << '"' << std::endl; } if(X509_set_issuer_name(x509.get(),name) != 1){ throw_system_error_ssl("Could not set X509 issuer name"); } std::cerr << "set issuer name" << std::endl; std::unique_ptr<EVP_MD_CTX,void(*)(EVP_MD_CTX*)> mctx(EVP_MD_CTX_create(),&EVP_MD_CTX_destroy); // EVP_PKEY_CTX *pkctx(nullptr); if(EVP_DigestSignInit(mctx.get(),nullptr,EVP_sha256(),nullptr,privKey.get()) != 1){ throw_system_error_ssl("Could not init EVP Digest Sign"); } std::cerr << "initialized EVP MD CTX" << std::endl; if(X509_sign_ctx(x509.get(),mctx.get()) <= 0){ throw_system_error_ssl("Could not sign certificate"); } std::cerr << "signed" << std::endl; std::unique_ptr<BIO,void(*)(BIO*)> x509BIO(BIO_new_file(x509Filename.c_str(),"w"),&BIO_free_all); if(PEM_write_bio_X509(x509BIO.get(),x509.get()) != 1){ throw_system_error_ssl("Could not write X509 certificate"); } std::cerr << "written to " << x509Filename << std::endl; }
void UpdateChecker::unpackUpdate() { QByteArray packed; if (!outputFile.open(QIODevice::ReadOnly)) { LOG(("Update Error: cant read updates file!")); return fatalFail(); } #ifdef Q_OS_WIN // use Lzma SDK for win const int32 hSigLen = 128, hShaLen = 20, hPropsLen = LZMA_PROPS_SIZE, hOriginalSizeLen = sizeof(int32), hSize = hSigLen + hShaLen + hPropsLen + hOriginalSizeLen; // header #else // Q_OS_WIN const int32 hSigLen = 128, hShaLen = 20, hPropsLen = 0, hOriginalSizeLen = sizeof(int32), hSize = hSigLen + hShaLen + hOriginalSizeLen; // header #endif // Q_OS_WIN QByteArray compressed = outputFile.readAll(); int32 compressedLen = compressed.size() - hSize; if (compressedLen <= 0) { LOG(("Update Error: bad compressed size: %1").arg(compressed.size())); return fatalFail(); } outputFile.close(); QString tempDirPath = cWorkingDir() + qsl("tupdates/temp"), readyFilePath = cWorkingDir() + qsl("tupdates/temp/ready"); psDeleteDir(tempDirPath); QDir tempDir(tempDirPath); if (tempDir.exists() || QFile(readyFilePath).exists()) { LOG(("Update Error: cant clear tupdates/temp dir!")); return fatalFail(); } uchar sha1Buffer[20]; bool goodSha1 = !memcmp(compressed.constData() + hSigLen, hashSha1(compressed.constData() + hSigLen + hShaLen, compressedLen + hPropsLen + hOriginalSizeLen, sha1Buffer), hShaLen); if (!goodSha1) { LOG(("Update Error: bad SHA1 hash of update file!")); return fatalFail(); } RSA *pbKey = PEM_read_bio_RSAPublicKey(BIO_new_mem_buf(const_cast<char*>(AppAlphaVersion ? UpdatesPublicAlphaKey : UpdatesPublicKey), -1), 0, 0, 0); if (!pbKey) { LOG(("Update Error: cant read public rsa key!")); return fatalFail(); } if (RSA_verify(NID_sha1, (const uchar*)(compressed.constData() + hSigLen), hShaLen, (const uchar*)(compressed.constData()), hSigLen, pbKey) != 1) { // verify signature RSA_free(pbKey); if (cAlphaVersion() || cBetaVersion()) { // try other public key, if we are in alpha or beta version pbKey = PEM_read_bio_RSAPublicKey(BIO_new_mem_buf(const_cast<char*>(AppAlphaVersion ? UpdatesPublicKey : UpdatesPublicAlphaKey), -1), 0, 0, 0); if (!pbKey) { LOG(("Update Error: cant read public rsa key!")); return fatalFail(); } if (RSA_verify(NID_sha1, (const uchar*)(compressed.constData() + hSigLen), hShaLen, (const uchar*)(compressed.constData()), hSigLen, pbKey) != 1) { // verify signature RSA_free(pbKey); LOG(("Update Error: bad RSA signature of update file!")); return fatalFail(); } } else { LOG(("Update Error: bad RSA signature of update file!")); return fatalFail(); } } RSA_free(pbKey); QByteArray uncompressed; int32 uncompressedLen; memcpy(&uncompressedLen, compressed.constData() + hSigLen + hShaLen + hPropsLen, hOriginalSizeLen); uncompressed.resize(uncompressedLen); size_t resultLen = uncompressed.size(); #ifdef Q_OS_WIN // use Lzma SDK for win SizeT srcLen = compressedLen; int uncompressRes = LzmaUncompress((uchar*)uncompressed.data(), &resultLen, (const uchar*)(compressed.constData() + hSize), &srcLen, (const uchar*)(compressed.constData() + hSigLen + hShaLen), LZMA_PROPS_SIZE); if (uncompressRes != SZ_OK) { LOG(("Update Error: could not uncompress lzma, code: %1").arg(uncompressRes)); return fatalFail(); } #else // Q_OS_WIN lzma_stream stream = LZMA_STREAM_INIT; lzma_ret ret = lzma_stream_decoder(&stream, UINT64_MAX, LZMA_CONCATENATED); if (ret != LZMA_OK) { const char *msg; switch (ret) { case LZMA_MEM_ERROR: msg = "Memory allocation failed"; break; case LZMA_OPTIONS_ERROR: msg = "Specified preset is not supported"; break; case LZMA_UNSUPPORTED_CHECK: msg = "Specified integrity check is not supported"; break; default: msg = "Unknown error, possibly a bug"; break; } LOG(("Error initializing the decoder: %1 (error code %2)").arg(msg).arg(ret)); return fatalFail(); } stream.avail_in = compressedLen; stream.next_in = (uint8_t*)(compressed.constData() + hSize); stream.avail_out = resultLen; stream.next_out = (uint8_t*)uncompressed.data(); lzma_ret res = lzma_code(&stream, LZMA_FINISH); if (stream.avail_in) { LOG(("Error in decompression, %1 bytes left in _in of %2 whole.").arg(stream.avail_in).arg(compressedLen)); return fatalFail(); } else if (stream.avail_out) { LOG(("Error in decompression, %1 bytes free left in _out of %2 whole.").arg(stream.avail_out).arg(resultLen)); return fatalFail(); } lzma_end(&stream); if (res != LZMA_OK && res != LZMA_STREAM_END) { const char *msg; switch (res) { case LZMA_MEM_ERROR: msg = "Memory allocation failed"; break; case LZMA_FORMAT_ERROR: msg = "The input data is not in the .xz format"; break; case LZMA_OPTIONS_ERROR: msg = "Unsupported compression options"; break; case LZMA_DATA_ERROR: msg = "Compressed file is corrupt"; break; case LZMA_BUF_ERROR: msg = "Compressed data is truncated or otherwise corrupt"; break; default: msg = "Unknown error, possibly a bug"; break; } LOG(("Error in decompression: %1 (error code %2)").arg(msg).arg(res)); return fatalFail(); } #endif // Q_OS_WIN tempDir.mkdir(tempDir.absolutePath()); quint32 version; { QBuffer buffer(&uncompressed); buffer.open(QIODevice::ReadOnly); QDataStream stream(&buffer); stream.setVersion(QDataStream::Qt_5_1); stream >> version; if (stream.status() != QDataStream::Ok) { LOG(("Update Error: cant read version from downloaded stream, status: %1").arg(stream.status())); return fatalFail(); } quint64 betaVersion = 0; if (version == 0x7FFFFFFF) { // beta version stream >> betaVersion; if (stream.status() != QDataStream::Ok) { LOG(("Update Error: cant read beta version from downloaded stream, status: %1").arg(stream.status())); return fatalFail(); } if (!cBetaVersion() || betaVersion <= cBetaVersion()) { LOG(("Update Error: downloaded beta version %1 is not greater, than mine %2").arg(betaVersion).arg(cBetaVersion())); return fatalFail(); } } else if (int32(version) <= AppVersion) {