在 PostgreSQL 中准备、存储、检索加密数据

Posted

技术标签:

【中文标题】在 PostgreSQL 中准备、存储、检索加密数据【英文标题】:Preparing, Storing, Retrieving Encrypted Data in PostgreSQL 【发布时间】:2013-02-18 05:19:38 【问题描述】:

有谁知道如何正确准备将 BYTEA 数据类型插入到 postgresql 中?我有一个从 libmcrypt 生成的加密字符串。我希望将加密存储在定义为的表列中 “cdata bytea 不为空”

我的核心与命令行完美配合,但现在我希望将加密存储在 RDBMS 中,作为对文件的操作。代码 sn-p 如下:

int rs;
char buffer[1];
char dbuffer[1024];
datafile = "This is my house";  // assume this to be a file
crypt_key[] = "12345678901234567890123456789012";  //  32 bytes
crypt_iv[] =  "11111111111111111111111111111111";  // 32 bytes
mfd = mcrypt_module_open(MCRYPT_RIJNDAEL_256, NULL, "cfb", NULL);  // assume success
mcrypt_generic_init(mfd, crypt_Key, 32,crypt_iv);  // assume success

while(readInputFile(datafile,buffer,sizeof(buffer),&bytes) == cgiFormSuccess) 
        mcrypt_generic(mfd,buffer,sizeof(buffer));  // buffer size s/b 1
        dbuffer[i++] = *buffer;
        dbuffer[i] = '\0';  // Time spent on string sanity
  // processed each byte is now encrypted

// Now I wish to prepare dbuffer for table insertion
sb = PQescapeByteaConn(dbconn,dbuffer,(size_t)strlen(dbuffer),&rs);

// Perform Insertion --> cdata::BYTEA
sprintf(query,"INSERT INTO crypto (uid,crypt_key,crypt_iv,cdata,cfile)"
                  "VALUES('%s','%s','%s','%s','%s')",
         ebs->uid,ebs->crkey,ebs->crivs,sb,credf);  // cfile == original filename
ebs->r=db_func_query(ebs->r,query,0,proc);  // Please assume DB command success

// Expected output sb == \x...some hex, dbuffer == encrypted bytes.  sb is now in bytea table column.
######################################
// Prepare to decrypt the cdata::bytea column

sprintf(query,"DECLARE %s CURSOR FOR SELECT crypt_iv,cdata,cfile "  // not sure if cursor s/b regular or binary for this
                  "FROM crypto WHERE uid='%s' AND crypt_iv='%s' AND action=true",
         VCURSOR,ebs->uid,ebs->crkey);

db_func_txn_begin(ebs->r,proc);
ebs->r = db_func_query(ebs->r,query,1,proc);  // process the query and assume it delivers the row
if(totalrow) 
     nFields = PQnfields(ebs->r);
     char* results[nFields];
     for(i = 0;i < totalrow;i++) 
          for(j = 0;j < nFields;j++)
               results[j] = PQgetvalue(ebs->r,i,j);
          strcpy(crypt_iv,results[0]);
          strcpy(dbuffer,results[1]);
          strcpy(cfile,results[2]);

mcrypt_generic_init(mfd, crypt_Key, 32,crypt_iv);  // assume success
sb = PQunescapeBytea(dataBuf,&rs);

for(i = 0;i < rs+1;i++) 
     mdecrypt_generic(mfd,sb[i],1);  // buffer size s/b 1
     dbuffer[i] = sb[i];
     dbuffer[i+1] = '\0';  // Time spent on string sanity


// Expected output sb == reverse of PQescapeByteaConn, dbuffer == unencrypted bytes.

必须有一种方法可以成功插入和查询加密字符串以进行解密。

提前致谢。

【问题讨论】:

来自 pgsql-hackers 的交叉帖子:postgresql.org/message-id/…。稍后发现此内容的读者也应该查看该线程,以防稍后发布相关信息。 顺便说一句,这段代码确实应该使用 libpq 的参数化查询接口,以确保它免受任何可能的 SQL 注入风险,并且更容易调试和转义。 您提到的过程 db 处理过程只是我的 libpq 库调用的包装器,因此可以减少编写的行数,并且它已经工作了多年,没有任何已知或报告的妥协。但是,我正在尝试找到解决加密输出时遇到的二进制字符串问题的答案,并且我相信我正在使用的准备技术。此代码与文件 I/O 完美配合,但不适用于 DB 插入调用。我正在为 PSQL 9.2.3 版开发这个 好的...如果您将加密字节打印到控制台,您还写入了数据库,您能否验证它们在数据库中是否相同?即您的代码的写入端或读取端有问题吗? 克雷格,是的,控制台和数据库内容是相同的。如果我注释掉加密和 PGescapeByteaConn 调用,我会验证我实际尝试加密的内容。问题似乎始于 PGencryptByteaConn。 【参考方案1】:

问题已解决。只要您转义 mcrypted 字符串的输出,您就可以只使用一个文本列。 Bytea 更干净但代码行更多,而且 PGunescapeBytea 显然是解密所必需的。

【讨论】:

以上是关于在 PostgreSQL 中准备、存储、检索加密数据的主要内容,如果未能解决你的问题,请参考以下文章

双向加密:我需要存储可以检索的密码

双向加密:我需要存储可以检索的密码

使用 NodeJS,如何使用 Spring Security OAuth2 制作的 JWT 检索存储在 PostgreSQL 中的会话信息?

PostgreSQL用户密码如何通过md5加密存储,是否加了salt

如何在Postgresql中创建序列数并应用在数据表

如何在Postgresql中创建序列数并应用在数据表