Encrypt/Decrypt between Postgres and Node

ぃ、小莉子 提交于 2020-08-25 21:19:07

问题


Problem: We have to encrypt a certain column on a certain table (Postgres). It has to be decryptable in SQL queries and in our nodejs/sequelize application layer. The encryption can happen in either layer, but it must be decodable from either.

The issue I'm running into (and I'm sure it's user error) is that if I encrypt in the db I can only decrypt in the db, and the same for node.

I've tried using PGP_SYM_ENCRYPT and ENCRYPT in postgres and crypto and crypto-js/aes in node. I've gotten it to the point where it's decrypting without an error, but returns gibberish.

A few things I've tried so far (test key is thirtytwocharsthirtytwocharsplus):

set() {
  this.setDataValue('field', seq.cast(seq.fn('PGP_SYM_ENCRYPT', val, 
  config.AES_KEY), 'text'))
}

This properly writes the field such that PGP_SYM_DECRYPT will decrypt it, but there's (apparently?) no way to tell Sequelize to wrap the field name with a function call so it's a lot of extra js that I feel is avoidable

const decipher = crypto.createDecipher('aes256', config.AES_KEY)
decipher.setAutoPadding(false);
return decipher.update(new Buffer(this.getDataValue('field', 'binary'), 'binary', 'ascii')) + decipher.final('ascii')

This will decode the field but returns gibberish (�Mq��8Ya�b) instead of the value (test)

aes.encrypt('test', config.AES_KEY)
aes.decrypt(field, config.AES_KEY).toString(CryptoJS.enc.Utf8)

This encrypts fine, decrypts fine, but Postgres errors when trying to decrypt (using either PGP_SYM_DECRYPT or DECRYPT). Casting the resulting field to ::TEXT and pasting it into an online AES Decrypter returns the expected value.

I really want to avoid having to add a bunch of boilerplate to our node repositories/queries, and I really feel like this should work. Using the same crypto algorithm should yield the same results

Any nudge or pointer would be greatly appreciated


回答1:


Postgres has rather unclear documentation about the raw encryption functions. After a few tries and failures, I managed to replicate most of logic logic in nodejs.

Here is the program I used.

const crypto = require('crypto');

const iv = Buffer.alloc(16); // zeroed-out iv

function encrypt(plainText, algorithm, key) {
  const cipher = crypto.createCipheriv(algorithm, key, iv);
  let encrypted = cipher.update(plainText, 'utf8', 'base64');
  encrypted += cipher.final('base64');
  return encrypted;
}

function decrypt(encrypted, algorithm, key) {
  const decrypt = crypto.createDecipheriv(algorithm, key, iv);
  let text = decrypt.update(encrypted, 'base64', 'utf8');
  text += decrypt.final('utf8')
  return text;
}

const originalText = "hello world";
const userKey = 'abcd'
const algorithm = 'aes-128-cbc';

const paddedKey = Buffer.concat([Buffer.from(userKey), Buffer.alloc(12)]); // make it 128 bits key

const hw = encrypt(originalText, algorithm, paddedKey);
console.log("original", originalText);
console.log("encrypted:", hw);
console.log("decoded: ", decrypt(hw, algorithm, paddedKey).toString());

Also here is a list of things not documented for the raw functions of postgres:

  • the key will be auto padded to match one of the 3 lengths: 128 bits, 192 bits, 256 bits
  • algorithm is automatically upgraded, when key length exceeds the limit. e.g. if key exceeds 128bits, aes-192-cbc will be used to encrypt
  • if key exceeds 256 bits, it will be truncated to 256 bits.

It would be easier to replicate it in application language (either Javascript or Java), if Postgres has proper documentation of these functions.




回答2:


Ok, I got it working, hopefully properly

What I did was:

Encrypting with crypto.createCipheriv('aes-256-cbc', new Buffer(config.AES_KEY), iv) in node, encrypt_iv in pgsql and storing as hex in the db, and decrypting with crypto.createDecipheriv/decrypt_iv into text/utf8

I don't know what part I was missing, but between specifying aes256, using the iv methods, and flipping juggling hex/text it seems to be working.

👍



来源:https://stackoverflow.com/questions/50475641/encrypt-decrypt-between-postgres-and-node

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!