I have a NodeJS script, that reads PDFs, I was wondering how one can go about decrypting a PDF with a supplied password with NodeJS specific.
You can use node-qpdf npm module(https://www.npmjs.com/package/node-qpdf)
Simple example code found in the documentation of node-qpdf module is:
To encrypt a pdf
var qpdf = require('node-qpdf');
var options = {
keyLength: 128,
password: 'YOUR_PASSWORD_TO_ENCRYPT',
restrictions: {
print: 'low',
useAes: 'y'
}
}
qpdf.encrypt(localFilePath, options, outputFilePath);
To decrypt the pdf
var qpdf = require('node-qpdf');
qpdf.decrypt(localFilePath, 'YOUR_PASSWORD_TO_DECRYPT_PDF', outputFilePath);
I also try to decrpt password protected pdf using below function but don't know how to get base64 data or file
const qpdf = require('node-qpdf');
await qpdf.decrypt('lic_demo.pdf', 'awxpt1377q12081992', 'demo.pdf');
Related
I'm encrypting a a text file locally using the crypto module from node.js and upload the file to IPFS. I'm trying to then download the file and decrypt it. But once I upload the encrypted file to IPFS, it seems to change to a buffer.
It looks somewhat like this before upload (I only copied the first line):
N�&��6-d�9L% 9���E��k�ir�C��ڤ|%B5-(���i�
...
...
And it looks like this after download:
{"type":"Buffer","data":[1,78,211,38,190,164,54,25,...])
I tried to convert it to multiple encodings, but that doesn't seem to solve anything. Is there a way to upload it in a different format (which stays the same on IPFS) or is there a way to convert the buffer back and decrypt it?
This is the code I use for encryption:
export const encrypt = (buffer, key) => {
const algorithm = 'aes-256-ctr';
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv(algorithm, key, iv);
const result = Buffer.concat([iv, cipher.update(buffer), cipher.final()]);
return result;
};
I am new to Python.I want to use Google text-to-speech API for that i used below code, but I am unable to access the API due to error. This is the code,
def synthesize_text(text):
"""Synthesizes speech from the input string of text."""
from google.cloud import texttospeech
client = texttospeech.TextToSpeechClient()
input_text = texttospeech.types.SynthesisInput(text=text)
# Note: the voice can also be specified by name.
# Names of voices can be retrieved with client.list_voices().
voice = texttospeech.types.VoiceSelectionParams(
language_code='en-US',
ssml_gender=texttospeech.enums.SsmlVoiceGender.FEMALE)
audio_config = texttospeech.types.AudioConfig(
audio_encoding=texttospeech.enums.AudioEncoding.MP3)
response = client.synthesize_speech(input_text, voice, audio_config)
# The response's audio_content is binary.
with open('output.mp3', 'wb') as out:
out.write(response.audio_content)
print('Audio content written to file "output.mp3"')
This is the error,
google.auth.exceptions.DefaultCredentialsError: Could not automatically determine credentials. Please set GOOGLE_APPLICATION_CREDENTIALS or
explicitly create credential and re-run the application. For more
information, please see
https://developers.google.com/accounts/docs/application-default-credentials.
I already have credentials JSON file, but I am unable to configure the code to authenticate my request.
Please help!
You could try this code:
from google.oauth2 import service_account
credentials = service_account.Credentials.from_service_account_file('yourkey.json')
client = texttospeech.TextToSpeechClient(credentials=credentials)
There are 2 ways :
1 Way :
if you using Json file then better to set json path into Environment Variable, if you do this then you no need to setup in coding it will automatically get you license from there
GOOGLE_APPLICATION_CREDENTIALS=[path]
2 WAY :
I have Java code i don't know about python so you can get idea from here :
String jsonPath = "file.json";
CredentialsProvider credentialsProvider = FixedCredentialsProvider.create(ServiceAccountCredentials.fromStream(new FileInputStream(jsonPath)));
TextToSpeechSettings settings = TextToSpeechSettings.newBuilder().setCredentialsProvider(credentialsProvider).build();
Instantiates a client
TextToSpeechClient textToSpeechClient = TextToSpeechClient.create(settings)
this seems to be an old discussion but I thought to comment, maybe someone will come across like in my case :))
for nodejs client, I managed to authenticate it this way:
const client = new textToSpeech.TextToSpeechClient({
credentials: {
private_key: "??",
client_email: "???",
}
});
You could authenticate your google credential by different ways.
One is by setting OS environment and another one is authenticate while you initiate a request.
I would suggest oauth2client library for python to authenticate.
In addition to this refer my example on Github (Link).
You need to have a service account, and service account .json key File.
You need to pass the key file name while you creating the client Instance.
const client = new textToSpeech.TextToSpeechClient({
keyFilename: "./auth.json",
});
Download the key file and rename it as auth.json place it root of your project folder.
Make sure Your service account have proper access to call the API.
Here is the full code:
// Imports the Google Cloud client library
const textToSpeech = require("#google-cloud/text-to-speech");
// Import other required libraries
const fs = require("fs");
const util = require("util");
// Creates a client
const client = new textToSpeech.TextToSpeechClient({
keyFilename: "./auth.json",
});
async function quickStart() {
// The text to synthesize
const text = "Hello this is a test";
// Construct the request
const request = {
input: { text: text },
// Select the language and SSML voice gender (optional)
voice: { languageCode: "en-US", ssmlGender: "NEUTRAL" },
// select the type of audio encoding
audioConfig: { audioEncoding: "MP3" },
};
// Performs the text-to-speech request
const [response] = await client.synthesizeSpeech(request);
// Write the binary audio content to a local file
const writeFile = util.promisify(fs.writeFile);
await writeFile("output.mp3", response.audioContent, "binary");
console.log("Audio content written to file: output.mp3");
}
quickStart();
I need to read a content of a password-protected archive (zip is preferred) to a node-js app, without writing the protected content to a file
In addition, the app is cross-platform so solution such this doesn't help
I looked also here but there is no code in the answer
The only library I can find that supports encryption is: https://github.com/rf00/minizip-asm.js
Unfortunately, it isn't well maintained.
This solution will read the file buffer which you can get from base64 or by reading the zip file, after that unzipping and opening the password-protected file is done in-memory. I hope this helps -
const unzipper = require("unzipper");
const unzipAndUnlockZipFileFromBuffer = async (zippedFileBase64, password) => {
try {
const zipBuffer = Buffer.from(zippedFileBase64, "base64"); // Change base64 to buffer
const zipDirectory = await unzipper.Open.buffer(zipBuffer); // unzip a buffered file
const file = zipDirectory.files[0]; // find the file you want
// if you want to find a specific file by path
// const file = zipDirectory.files.find((f) => f.path === "filename");
const extracted = await file.buffer(password); // unlock the file with the password
console.log(extracted.toString()); // file content
} catch (e) {
console.log(e);
}
};
const zippedFileBase64 = "{{BASE64}}";
const password = "1234";
unzipAndUnlockZipFileFromBuffer(zippedFileBase64, password);
I'm following the encryption example on this URL (code sample below) (http://lollyrock.com/articles/nodejs-encryption/). The problem is that I'm encrypting a .zip file, which seems to work just fine. The decryption is the problem. If I perform the code example below on something like a jpg, the picture comes out just fine. But if I run a zip file through it and I try to unzip the result, I get the following error:
End-of-central-directory signature not found. Either this file is not
a zipfile, or it constitutes one disk of a multi-part archive. In the
latter case the central directory and zipfile comment will be found on
the last disk(s) of this archive.
Code:
// Nodejs encryption of buffers
var crypto = require('crypto'),
algorithm = 'aes-256-ctr',
password = 'd6F3Efeq';
var fs = require('fs');
var zlib = require('zlib');
// input file
var r = fs.createReadStream('file.txt');
// zip content
var zip = zlib.createGzip();
// encrypt content
var encrypt = crypto.createCipher(algorithm, password);
// decrypt content
var decrypt = crypto.createDecipher(algorithm, password)
// unzip content
var unzip = zlib.createGunzip();
// write file
var w = fs.createWriteStream('file.out.txt');
// start pipe
r.pipe(zip).pipe(encrypt).pipe(decrypt).pipe(unzip).pipe(w);
So it turns out the difference in my code was it was reading from a request stream. Apparently you can't just pipe a request stream through gunzip through decryption? I'm not sure why.
But if I same the stream to a file and THEN run it through gunzip and decryption it works.
If anyone has any input as to why, I'd at least like to understand!
I need to encrypt a string using a public key (.pem file), and then sign it using a private key (also a .pem).
I am loading the .pem files fine:
publicCert = fs.readFileSync(publicCertFile).toString();
But after hours of scouring Google, I can't seem to find a way to encrypt data using the public key. In PHP I simply call openssl_public_encrypt(), but I don't see any corresponding function in Node.js or in any modules.
A library is not necessary. Enter crypto.
Here's a janky little module you could use to encrypt/decrypt strings with RSA keys:
var crypto = require("crypto");
var path = require("path");
var fs = require("fs");
var encryptStringWithRsaPublicKey = function(toEncrypt, relativeOrAbsolutePathToPublicKey) {
var absolutePath = path.resolve(relativeOrAbsolutePathToPublicKey);
var publicKey = fs.readFileSync(absolutePath, "utf8");
var buffer = Buffer.from(toEncrypt);
var encrypted = crypto.publicEncrypt(publicKey, buffer);
return encrypted.toString("base64");
};
var decryptStringWithRsaPrivateKey = function(toDecrypt, relativeOrAbsolutePathtoPrivateKey) {
var absolutePath = path.resolve(relativeOrAbsolutePathtoPrivateKey);
var privateKey = fs.readFileSync(absolutePath, "utf8");
var buffer = Buffer.from(toDecrypt, "base64");
var decrypted = crypto.privateDecrypt(privateKey, buffer);
return decrypted.toString("utf8");
};
module.exports = {
encryptStringWithRsaPublicKey: encryptStringWithRsaPublicKey,
decryptStringWithRsaPrivateKey: decryptStringWithRsaPrivateKey
}
I would recommend not using synchronous fs methods where possible, and you could use promises to make this better, but for simple use cases this is the approach that I have seen work and would take.
I tested this in Node.js 10, you can use encrypt/decrypt functions (small changes on Jacob's answer):
const crypto = require('crypto')
const path = require('path')
const fs = require('fs')
function encrypt(toEncrypt, relativeOrAbsolutePathToPublicKey) {
const absolutePath = path.resolve(relativeOrAbsolutePathToPublicKey)
const publicKey = fs.readFileSync(absolutePath, 'utf8')
const buffer = Buffer.from(toEncrypt, 'utf8')
const encrypted = crypto.publicEncrypt(publicKey, buffer)
return encrypted.toString('base64')
}
function decrypt(toDecrypt, relativeOrAbsolutePathtoPrivateKey) {
const absolutePath = path.resolve(relativeOrAbsolutePathtoPrivateKey)
const privateKey = fs.readFileSync(absolutePath, 'utf8')
const buffer = Buffer.from(toDecrypt, 'base64')
const decrypted = crypto.privateDecrypt(
{
key: privateKey.toString(),
passphrase: '',
},
buffer,
)
return decrypted.toString('utf8')
}
const enc = encrypt('hello', `public.pem`)
console.log('enc', enc)
const dec = decrypt(enc, `private.pem`)
console.log('dec', dec)
For the keys you can generate them with
const { writeFileSync } = require('fs')
const { generateKeyPairSync } = require('crypto')
function generateKeys() {
const { privateKey, publicKey } = generateKeyPairSync('rsa', {
modulusLength: 4096,
publicKeyEncoding: {
type: 'pkcs1',
format: 'pem',
},
privateKeyEncoding: {
type: 'pkcs1',
format: 'pem',
cipher: 'aes-256-cbc',
passphrase: '',
},
})
writeFileSync('private.pem', privateKey)
writeFileSync('public.pem', publicKey)
}
The updated public/private decrypt and encryption module is URSA. The node-rsa module is outdated.
This Node module provides a fairly complete set of wrappers for the
RSA public/private key crypto functionality of OpenSSL.
npm install ursa
Use the node-rsa module. Here's a link to the test.js file that demonstrates usage.
TL;DR: URSA is your best bet. It's really funky that this doesn't come standard with Node.js' crypto.
Every other solutions I found either doesn't work in Windows or aren't actually encryption libraries. URSA, recommended by Louie, looks like the best bet. If you don't care about Windows, you're even more golden.
Note on Ursa: I had to install OpenSSL along with something called "Visual C++ 2008 Redistributables" in order to get the npm install to work. Get that junk here: http://slproweb.com/products/Win32OpenSSL.html
The breakdown:
Annoying additional manual installation steps for Windows
https://github.com/Obvious/ursa - probably the best of the lot
Not compatible with Windows
https://npmjs.org/package/rsautl - says BADPLATFORM
https://github.com/katyo/node-rsa - node-waf isn't available on Windows
https://github.com/paspao/simple_rsa_encrypt - unistd.h isn't on windows
https://npmjs.org/package/pripub - large amounts of linker errors, also not on GitHub
Not encryption libraries
https://github.com/substack/secure-peer
https://github.com/substack/rsa-json - just generates keys, but doesn't use them
https://github.com/substack/rsa-unpack - just unpacks PEM strings
This is literally all I could find.
This is not supported natively by Node.js version v0.11.13 or below, but it seems that next version of Node.js (a.k.a v0.12) will support this.
Here is the clue: https://github.com/joyent/node/blob/v0.12/lib/crypto.js#L358
See crypto.publicEncrypt and crypto.privateDecrypt
Here is the future documentation for this
https://github.com/joyent/node/blob/7c0419730b237dbfa0ec4e6fb33a99ff01825a8f/doc/api/crypto.markdown#cryptopublicencryptpublic_key-buffer