Implement MIME message type (Literal Data Packet format 'm')
This commit is contained in:
parent
3b81088aaf
commit
6f2abdc2cf
|
@ -212,7 +212,9 @@ export default {
|
||||||
/** Text data 't' */
|
/** Text data 't' */
|
||||||
text: 't'.charCodeAt(),
|
text: 't'.charCodeAt(),
|
||||||
/** Utf8 data 'u' */
|
/** Utf8 data 'u' */
|
||||||
utf8: 'u'.charCodeAt()
|
utf8: 'u'.charCodeAt(),
|
||||||
|
/** MIME message body part 'm' */
|
||||||
|
mime: 'm'.charCodeAt()
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -652,13 +652,14 @@ export function read(input) {
|
||||||
* @param {String} text
|
* @param {String} text
|
||||||
* @param {String} filename (optional)
|
* @param {String} filename (optional)
|
||||||
* @param {Date} date (optional)
|
* @param {Date} date (optional)
|
||||||
|
* @param {utf8|binary|text|mime} type (optional) data packet type
|
||||||
* @returns {module:message.Message} new message object
|
* @returns {module:message.Message} new message object
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
export function fromText(text, filename, date=new Date()) {
|
export function fromText(text, filename, date=new Date(), type='utf8') {
|
||||||
const literalDataPacket = new packet.Literal(date);
|
const literalDataPacket = new packet.Literal(date);
|
||||||
// text will be converted to UTF8
|
// text will be converted to UTF8
|
||||||
literalDataPacket.setText(text);
|
literalDataPacket.setText(text, type);
|
||||||
if (filename !== undefined) {
|
if (filename !== undefined) {
|
||||||
literalDataPacket.setFilename(filename);
|
literalDataPacket.setFilename(filename);
|
||||||
}
|
}
|
||||||
|
@ -672,19 +673,17 @@ export function fromText(text, filename, date=new Date()) {
|
||||||
* @param {Uint8Array} bytes
|
* @param {Uint8Array} bytes
|
||||||
* @param {String} filename (optional)
|
* @param {String} filename (optional)
|
||||||
* @param {Date} date (optional)
|
* @param {Date} date (optional)
|
||||||
|
* @param {utf8|binary|text|mime} type (optional) data packet type
|
||||||
* @returns {module:message.Message} new message object
|
* @returns {module:message.Message} new message object
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
export function fromBinary(bytes, filename, date=new Date()) {
|
export function fromBinary(bytes, filename, date=new Date(), type='binary') {
|
||||||
if (!util.isUint8Array(bytes)) {
|
if (!util.isUint8Array(bytes)) {
|
||||||
throw new Error('Data must be in the form of a Uint8Array');
|
throw new Error('Data must be in the form of a Uint8Array');
|
||||||
}
|
}
|
||||||
|
|
||||||
const literalDataPacket = new packet.Literal(date);
|
const literalDataPacket = new packet.Literal(date);
|
||||||
if (filename) {
|
literalDataPacket.setBytes(bytes, type);
|
||||||
literalDataPacket.setFilename(filename);
|
|
||||||
}
|
|
||||||
literalDataPacket.setBytes(bytes, enums.read(enums.literal, enums.literal.binary));
|
|
||||||
if (filename !== undefined) {
|
if (filename !== undefined) {
|
||||||
literalDataPacket.setFilename(filename);
|
literalDataPacket.setFilename(filename);
|
||||||
}
|
}
|
||||||
|
|
|
@ -213,6 +213,7 @@ export function encryptKey({ privateKey, passphrase }) {
|
||||||
* Encrypts message text/data with public keys, passwords or both at once. At least either public keys or passwords
|
* Encrypts message text/data with public keys, passwords or both at once. At least either public keys or passwords
|
||||||
* must be specified. If private keys are specified, those will be used to sign the message.
|
* must be specified. If private keys are specified, those will be used to sign the message.
|
||||||
* @param {String|Uint8Array} data text/data to be encrypted as JavaScript binary string or Uint8Array
|
* @param {String|Uint8Array} data text/data to be encrypted as JavaScript binary string or Uint8Array
|
||||||
|
* @param {utf8|binary|text|mime} dataType (optional) data packet type
|
||||||
* @param {Key|Array<Key>} publicKeys (optional) array of keys or single key, used to encrypt the message
|
* @param {Key|Array<Key>} publicKeys (optional) array of keys or single key, used to encrypt the message
|
||||||
* @param {Key|Array<Key>} privateKeys (optional) private keys for signing. If omitted message will not be signed
|
* @param {Key|Array<Key>} privateKeys (optional) private keys for signing. If omitted message will not be signed
|
||||||
* @param {String|Array<String>} passwords (optional) array of passwords or a single password to encrypt the message
|
* @param {String|Array<String>} passwords (optional) array of passwords or a single password to encrypt the message
|
||||||
|
@ -231,15 +232,15 @@ export function encryptKey({ privateKey, passphrase }) {
|
||||||
* @async
|
* @async
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
export function encrypt({ data, publicKeys, privateKeys, passwords, sessionKey, filename, compression=config.compression, armor=true, detached=false, signature=null, returnSessionKey=false, wildcard=false, date=new Date()}) {
|
export function encrypt({ data, dataType, publicKeys, privateKeys, passwords, sessionKey, filename, compression=config.compression, armor=true, detached=false, signature=null, returnSessionKey=false, wildcard=false, date=new Date()}) {
|
||||||
checkData(data); publicKeys = toArray(publicKeys); privateKeys = toArray(privateKeys); passwords = toArray(passwords);
|
checkData(data); publicKeys = toArray(publicKeys); privateKeys = toArray(privateKeys); passwords = toArray(passwords);
|
||||||
|
|
||||||
if (!nativeAEAD() && asyncProxy) { // use web worker if web crypto apis are not supported
|
if (!nativeAEAD() && asyncProxy) { // use web worker if web crypto apis are not supported
|
||||||
return asyncProxy.delegate('encrypt', { data, publicKeys, privateKeys, passwords, sessionKey, filename, compression, armor, detached, signature, returnSessionKey, wildcard, date });
|
return asyncProxy.delegate('encrypt', { data, dataType, publicKeys, privateKeys, passwords, sessionKey, filename, compression, armor, detached, signature, returnSessionKey, wildcard, date });
|
||||||
}
|
}
|
||||||
const result = {};
|
const result = {};
|
||||||
return Promise.resolve().then(async function() {
|
return Promise.resolve().then(async function() {
|
||||||
let message = createMessage(data, filename, date);
|
let message = createMessage(data, filename, date, dataType);
|
||||||
if (!privateKeys) {
|
if (!privateKeys) {
|
||||||
privateKeys = [];
|
privateKeys = [];
|
||||||
}
|
}
|
||||||
|
@ -314,6 +315,7 @@ export function decrypt({ message, privateKeys, passwords, sessionKeys, publicKe
|
||||||
/**
|
/**
|
||||||
* Signs a cleartext message.
|
* Signs a cleartext message.
|
||||||
* @param {String | Uint8Array} data cleartext input to be signed
|
* @param {String | Uint8Array} data cleartext input to be signed
|
||||||
|
* @param {utf8|binary|text|mime} dataType (optional) data packet type
|
||||||
* @param {Key|Array<Key>} privateKeys array of keys or single key with decrypted secret key data to sign cleartext
|
* @param {Key|Array<Key>} privateKeys array of keys or single key with decrypted secret key data to sign cleartext
|
||||||
* @param {Boolean} armor (optional) if the return value should be ascii armored or the message object
|
* @param {Boolean} armor (optional) if the return value should be ascii armored or the message object
|
||||||
* @param {Boolean} detached (optional) if the return value should contain a detached signature
|
* @param {Boolean} detached (optional) if the return value should contain a detached signature
|
||||||
|
@ -324,19 +326,19 @@ export function decrypt({ message, privateKeys, passwords, sessionKeys, publicKe
|
||||||
* @async
|
* @async
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
export function sign({ data, privateKeys, armor=true, detached=false, date=new Date() }) {
|
export function sign({ data, dataType, privateKeys, armor=true, detached=false, date=new Date() }) {
|
||||||
checkData(data);
|
checkData(data);
|
||||||
privateKeys = toArray(privateKeys);
|
privateKeys = toArray(privateKeys);
|
||||||
|
|
||||||
if (asyncProxy) { // use web worker if available
|
if (asyncProxy) { // use web worker if available
|
||||||
return asyncProxy.delegate('sign', {
|
return asyncProxy.delegate('sign', {
|
||||||
data, privateKeys, armor, detached, date
|
data, dataType, privateKeys, armor, detached, date
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = {};
|
const result = {};
|
||||||
return Promise.resolve().then(async function() {
|
return Promise.resolve().then(async function() {
|
||||||
let message = util.isString(data) ? new CleartextMessage(data) : messageLib.fromBinary(data);
|
let message = util.isString(data) ? new CleartextMessage(data) : messageLib.fromBinary(data, dataType);
|
||||||
|
|
||||||
if (detached) {
|
if (detached) {
|
||||||
const signature = await message.signDetached(privateKeys, undefined, date);
|
const signature = await message.signDetached(privateKeys, undefined, date);
|
||||||
|
@ -527,14 +529,15 @@ function toArray(param) {
|
||||||
* @param {String|Uint8Array} data the payload for the message
|
* @param {String|Uint8Array} data the payload for the message
|
||||||
* @param {String} filename the literal data packet's filename
|
* @param {String} filename the literal data packet's filename
|
||||||
* @param {Date} date the creation date of the package
|
* @param {Date} date the creation date of the package
|
||||||
|
* @param {utf8|binary|text|mime} type (optional) data packet type
|
||||||
* @returns {Message} a message object
|
* @returns {Message} a message object
|
||||||
*/
|
*/
|
||||||
function createMessage(data, filename, date=new Date()) {
|
function createMessage(data, filename, date=new Date(), type) {
|
||||||
let msg;
|
let msg;
|
||||||
if (util.isUint8Array(data)) {
|
if (util.isUint8Array(data)) {
|
||||||
msg = messageLib.fromBinary(data, filename, date);
|
msg = messageLib.fromBinary(data, filename, date, type);
|
||||||
} else if (util.isString(data)) {
|
} else if (util.isString(data)) {
|
||||||
msg = messageLib.fromText(data, filename, date);
|
msg = messageLib.fromText(data, filename, date, type);
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Data must be of type String or Uint8Array');
|
throw new Error('Data must be of type String or Uint8Array');
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ function Literal(date=new Date()) {
|
||||||
* Set the packet data to a javascript native string, end of line
|
* Set the packet data to a javascript native string, end of line
|
||||||
* will be normalized to \r\n and by default text is converted to UTF8
|
* will be normalized to \r\n and by default text is converted to UTF8
|
||||||
* @param {String} text Any native javascript string
|
* @param {String} text Any native javascript string
|
||||||
* @param {utf8|binary|text} format (optional) The format of the string of bytes
|
* @param {utf8|binary|text|mime} format (optional) The format of the string of bytes
|
||||||
*/
|
*/
|
||||||
Literal.prototype.setText = function(text, format='utf8') {
|
Literal.prototype.setText = function(text, format='utf8') {
|
||||||
this.format = format;
|
this.format = format;
|
||||||
|
@ -73,7 +73,7 @@ Literal.prototype.getText = function() {
|
||||||
/**
|
/**
|
||||||
* Set the packet data to value represented by the provided string of bytes.
|
* Set the packet data to value represented by the provided string of bytes.
|
||||||
* @param {Uint8Array} bytes The string of bytes
|
* @param {Uint8Array} bytes The string of bytes
|
||||||
* @param {utf8|binary|text} format The format of the string of bytes
|
* @param {utf8|binary|text|mime} format The format of the string of bytes
|
||||||
*/
|
*/
|
||||||
Literal.prototype.setBytes = function(bytes, format) {
|
Literal.prototype.setBytes = function(bytes, format) {
|
||||||
this.format = format;
|
this.format = format;
|
||||||
|
|
|
@ -1776,6 +1776,37 @@ describe('OpenPGP.js public api tests', function() {
|
||||||
}).then(function (packets) {
|
}).then(function (packets) {
|
||||||
const literals = packets.packets.filterByTag(openpgp.enums.packet.literal);
|
const literals = packets.packets.filterByTag(openpgp.enums.packet.literal);
|
||||||
expect(literals.length).to.equal(1);
|
expect(literals.length).to.equal(1);
|
||||||
|
expect(literals[0].format).to.equal('binary');
|
||||||
|
expect(+literals[0].date).to.equal(+future);
|
||||||
|
expect(packets.getLiteralData()).to.deep.equal(data);
|
||||||
|
return packets.verify(encryptOpt.publicKeys, future);
|
||||||
|
}).then(function (signatures) {
|
||||||
|
expect(+signatures[0].signature.packets[0].created).to.equal(+future);
|
||||||
|
expect(signatures[0].valid).to.be.true;
|
||||||
|
expect(encryptOpt.privateKeys[0].getSigningKeyPacket(signatures[0].keyid, future))
|
||||||
|
.to.be.not.null;
|
||||||
|
expect(signatures[0].signature.packets.length).to.equal(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should sign, encrypt and decrypt, verify mime data with a date in the future', function () {
|
||||||
|
const future = new Date(2040, 5, 5, 5, 5, 5, 0);
|
||||||
|
const data = new Uint8Array([3, 14, 15, 92, 65, 35, 59]);
|
||||||
|
const encryptOpt = {
|
||||||
|
data,
|
||||||
|
dataType: 'mime',
|
||||||
|
publicKeys: publicKey_2038_2045.keys,
|
||||||
|
privateKeys: privateKey_2038_2045.keys,
|
||||||
|
date: future,
|
||||||
|
armor: false
|
||||||
|
};
|
||||||
|
|
||||||
|
return openpgp.encrypt(encryptOpt).then(function (encrypted) {
|
||||||
|
return encrypted.message.decrypt(encryptOpt.privateKeys);
|
||||||
|
}).then(function (packets) {
|
||||||
|
const literals = packets.packets.filterByTag(openpgp.enums.packet.literal);
|
||||||
|
expect(literals.length).to.equal(1);
|
||||||
|
expect(literals[0].format).to.equal('mime');
|
||||||
expect(+literals[0].date).to.equal(+future);
|
expect(+literals[0].date).to.equal(+future);
|
||||||
expect(packets.getLiteralData()).to.deep.equal(data);
|
expect(packets.getLiteralData()).to.deep.equal(data);
|
||||||
return packets.verify(encryptOpt.publicKeys, future);
|
return packets.verify(encryptOpt.publicKeys, future);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user