diff --git a/ccm.js b/ccm.js new file mode 100644 index 0000000..9ed8401 --- /dev/null +++ b/ccm.js @@ -0,0 +1,156 @@ +var aes = require('./aes') +var Buffer = require('safe-buffer').Buffer +var Transform = require('cipher-base') +var inherits = require('inherits') +var xorInplace = require('buffer-xor/inplace') +var xorTest = require('timing-safe-equal') +function writeUIntBE (buff, value, start, length) { + if (length > 6) { + start += length - 6 + length = 6 + } + buff.writeUIntBE(value, start, length) +} + +function cbc (prev, data, self) { + var rump = 16 - (data.length % 16) + if (rump !== 16) { + data = Buffer.concat([data, Buffer.alloc(rump)]) + } + var place = 0 + while (place < data.length) { + xorInplace(prev, data.slice(place, place + 16)) + place += 16 + prev = self._cipher.encryptBlock(prev) + } + return prev +} +function StreamCipher (mode, key, iv, decrypt, options) { + Transform.call(this) + + if (!options || !options.authTagLength) throw new Error('options authTagLength is required') + + if (options.authTagLength < 4 || options.authTagLength > 16 || options.authTagLength % 2 === 1) throw new Error('authTagLength must be one of 4, 6, 8, 10, 12, 14 or 16') + + if (iv.length < 7 || iv.length > 13) throw new Error('iv must be between 7 and 13 bytes') + + this._n = iv.length + this._l = 15 - this._n + this._cipher = new aes.AES(key) + this.authTagLength = options.authTagLength + this._mode = mode + this._add = null + this._decrypt = decrypt + this._authTag = null + this._called = false + this._plainLength = null + this._prev = null + this._iv = iv + this._cache = Buffer.allocUnsafe(0) + this._failed = false + this._firstBlock = null +} +function validSize (ivLen, chunkLen) { + if (ivLen === 13 && chunkLen >= 65536) { + return false + } + if (ivLen === 12 && chunkLen >= 16777216) { + return false + } + return true +} +inherits(StreamCipher, Transform) +function createTag (self, data) { + var firstBlock = self._firstBlock + if (!firstBlock) { + firstBlock = Buffer.alloc(16) + firstBlock[0] = ((self.authTagLength - 2) / 2) * 8 + self._l - 1 + self._iv.copy(firstBlock, 1) + writeUIntBE(firstBlock, data.length, self._n + 1, self._l) + firstBlock = self._cipher.encryptBlock(firstBlock) + } + return cbc(firstBlock, data, self) +} +StreamCipher.prototype._update = function (chunk) { + if (this._called) throw new Error('Trying to add data in unsupported state') + + if (!validSize(this._iv.length, chunk.length)) throw new Error('Message exceeds maximum size') + + if (this._plainLength !== null && this._plainLength !== chunk.length) throw new Error('Trying to add data in unsupported state') + + this._called = true + this._prev = Buffer.alloc(16) + this._prev[0] = this._l - 1 + this._iv.copy(this._prev, 1) + var toXor + if (this._decrypt) { + toXor = this._mode.encrypt(this, Buffer.alloc(16)).slice(0, this.authTagLength) + } else { + this._authTag = this._mode.encrypt(this, createTag(this, chunk)).slice(0, this.authTagLength) + } + var out = this._mode.encrypt(this, chunk) + if (this._decrypt) { + var rawAuth = createTag(this, out).slice(0, this.authTagLength) + xorInplace(rawAuth, toXor) + this._failed = !xorTest(rawAuth, this._authTag) + } + this._cipher.scrub() + return out +} + +StreamCipher.prototype._final = function () { + if (this._decrypt && !this._authTag) throw new Error('Unsupported state or unable to authenticate data') + + if (this._failed) throw new Error('Unsupported state or unable to authenticate data') +} + +StreamCipher.prototype.getAuthTag = function getAuthTag () { + if (this._decrypt || !Buffer.isBuffer(this._authTag)) throw new Error('Attempting to get auth tag in unsupported state') + + return this._authTag +} + +StreamCipher.prototype.setAuthTag = function setAuthTag (tag) { + if (!this._decrypt) throw new Error('Attempting to set auth tag in unsupported state') + + this._authTag = tag +} + +StreamCipher.prototype.setAAD = function setAAD (buf, options) { + if (this._called) throw new Error('Attempting to set AAD in unsupported state') + + if (!options || !options.plaintextLength) throw new Error('options plaintextLength is required') + + if (!validSize(this._iv.length, options.plaintextLength)) throw new Error('Message exceeds maximum size') + + this._plainLength = options.plaintextLength + + if (!buf.length) return + + var firstBlock = Buffer.alloc(16) + firstBlock[0] = 64 + ((this.authTagLength - 2) / 2) * 8 + this._l - 1 + this._iv.copy(firstBlock, 1) + writeUIntBE(firstBlock, options.plaintextLength, this._n + 1, this._l) + firstBlock = this._cipher.encryptBlock(firstBlock) + + var la = buf.length + var ltag + if (la < 65280) { + ltag = Buffer.allocUnsafe(2) + ltag.writeUInt16BE(la, 0) + } else if (la < 4294967296) { + ltag = Buffer.allocUnsafe(6) + ltag[0] = 0xff + ltag[1] = 0xfe + ltag.writeUInt32BE(la, 2) + } else { + ltag = Buffer.alloc(10) + ltag[0] = 0xff + ltag[1] = 0xff + ltag.writeUIntBE(la, 4, 6) + } + var aToAuth = Buffer.concat([ltag, buf]) + this._firstBlock = cbc(firstBlock, aToAuth, this) +} + +module.exports = StreamCipher diff --git a/decrypter.js b/decrypter.js index 740b2e6..1ad51af 100644 --- a/decrypter.js +++ b/decrypter.js @@ -1,4 +1,5 @@ -var AuthCipher = require('./authCipher') +var GCM = require('./gcm') +var CCM = require('./ccm') var Buffer = require('safe-buffer').Buffer var MODES = require('./modes') var StreamCipher = require('./streamCipher') @@ -93,31 +94,33 @@ function unpad (last) { return last.slice(0, 16 - padded) } -function createDecipheriv (suite, password, iv) { +function createDecipheriv (suite, password, iv, options) { var config = MODES[suite.toLowerCase()] if (!config) throw new TypeError('invalid suite type') if (typeof iv === 'string') iv = Buffer.from(iv) - if (config.mode !== 'GCM' && iv.length !== config.iv) throw new TypeError('invalid iv length ' + iv.length) + if (config.type !== 'auth' && iv.length !== config.iv) throw new TypeError('invalid iv length ' + iv.length) if (typeof password === 'string') password = Buffer.from(password) if (password.length !== config.key / 8) throw new TypeError('invalid key length ' + password.length) if (config.type === 'stream') { return new StreamCipher(config.module, password, iv, true) - } else if (config.type === 'auth') { - return new AuthCipher(config.module, password, iv, true) + } else if (config.mode === 'GCM') { + return new GCM(config.module, password, iv, true) + } else if (config.mode === 'CCM') { + return new CCM(config.module, password, iv, true, options) } return new Decipher(config.module, password, iv) } -function createDecipher (suite, password) { +function createDecipher (suite, password, options) { var config = MODES[suite.toLowerCase()] if (!config) throw new TypeError('invalid suite type') var keys = ebtk(password, false, config.key, config.iv) - return createDecipheriv(suite, keys.key, keys.iv) + return createDecipheriv(suite, keys.key, keys.iv, options) } exports.createDecipher = createDecipher diff --git a/encrypter.js b/encrypter.js index 0c4c58b..3cc6847 100644 --- a/encrypter.js +++ b/encrypter.js @@ -1,5 +1,6 @@ var MODES = require('./modes') -var AuthCipher = require('./authCipher') +var GCM = require('./gcm') +var CCM = require('./ccm') var Buffer = require('safe-buffer').Buffer var StreamCipher = require('./streamCipher') var Transform = require('cipher-base') @@ -83,7 +84,7 @@ Splitter.prototype.flush = function () { return Buffer.concat([this.cache, padBuff]) } -function createCipheriv (suite, password, iv) { +function createCipheriv (suite, password, iv, options) { var config = MODES[suite.toLowerCase()] if (!config) throw new TypeError('invalid suite type') @@ -91,23 +92,25 @@ function createCipheriv (suite, password, iv) { if (password.length !== config.key / 8) throw new TypeError('invalid key length ' + password.length) if (typeof iv === 'string') iv = Buffer.from(iv) - if (config.mode !== 'GCM' && iv.length !== config.iv) throw new TypeError('invalid iv length ' + iv.length) + if (config.type !== 'auth' && iv.length !== config.iv) throw new TypeError('invalid iv length ' + iv.length) if (config.type === 'stream') { return new StreamCipher(config.module, password, iv) - } else if (config.type === 'auth') { - return new AuthCipher(config.module, password, iv) + } else if (config.mode === 'GCM') { + return new GCM(config.module, password, iv) + } else if (config.mode === 'CCM') { + return new CCM(config.module, password, iv, false, options) } return new Cipher(config.module, password, iv) } -function createCipher (suite, password) { +function createCipher (suite, password, options) { var config = MODES[suite.toLowerCase()] if (!config) throw new TypeError('invalid suite type') var keys = ebtk(password, false, config.key, config.iv) - return createCipheriv(suite, keys.key, keys.iv) + return createCipheriv(suite, keys.key, keys.iv, options) } exports.createCipheriv = createCipheriv diff --git a/authCipher.js b/gcm.js similarity index 88% rename from authCipher.js rename to gcm.js index c6e8a76..eca838c 100644 --- a/authCipher.js +++ b/gcm.js @@ -5,19 +5,7 @@ var inherits = require('inherits') var GHASH = require('./ghash') var xor = require('buffer-xor') var incr32 = require('./incr32') - -function xorTest (a, b) { - var out = 0 - if (a.length !== b.length) out++ - - var len = Math.min(a.length, b.length) - for (var i = 0; i < len; ++i) { - out += (a[i] ^ b[i]) - } - - return out -} - +var xorTest = require('timing-safe-equal') function calcIv (self, iv, ck) { if (iv.length === 12) { self._finID = Buffer.concat([iv, Buffer.from([0, 0, 0, 1])]) @@ -34,7 +22,7 @@ function calcIv (self, iv, ck) { ghash.update(Buffer.alloc(8, 0)) var ivBits = len * 8 var tail = Buffer.alloc(8) - tail.writeUIntBE(ivBits, 0, 8) + tail.writeUIntBE(ivBits, 2, 6) ghash.update(tail) self._finID = ghash.state var out = Buffer.from(self._finID) @@ -89,7 +77,7 @@ StreamCipher.prototype._final = function () { if (this._decrypt && !this._authTag) throw new Error('Unsupported state or unable to authenticate data') var tag = xor(this._ghash.final(this._alen * 8, this._len * 8), this._cipher.encryptBlock(this._finID)) - if (this._decrypt && xorTest(tag, this._authTag)) throw new Error('Unsupported state or unable to authenticate data') + if (this._decrypt && !xorTest(tag, this._authTag)) throw new Error('Unsupported state or unable to authenticate data') this._authTag = tag this._cipher.scrub() diff --git a/modes/index.js b/modes/index.js index 767d6cb..b63ab9f 100644 --- a/modes/index.js +++ b/modes/index.js @@ -6,7 +6,8 @@ var modeModules = { CFB1: require('./cfb1'), OFB: require('./ofb'), CTR: require('./ctr'), - GCM: require('./ctr') + GCM: require('./ctr'), + CCM: require('./ctr') } var modes = require('./list.json') diff --git a/modes/list.json b/modes/list.json index 33de25b..b6490e2 100644 --- a/modes/list.json +++ b/modes/list.json @@ -187,5 +187,26 @@ "iv": 12, "mode": "GCM", "type": "auth" + }, + "aes-128-ccm": { + "cipher": "AES", + "key": 128, + "iv": 12, + "mode": "CCM", + "type": "auth" + }, + "aes-192-ccm": { + "cipher": "AES", + "key": 192, + "iv": 12, + "mode": "CCM", + "type": "auth" + }, + "aes-256-ccm": { + "cipher": "AES", + "key": 256, + "iv": 12, + "mode": "CCM", + "type": "auth" } } diff --git a/package.json b/package.json index ff26b87..7b7aef2 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,8 @@ "create-hash": "^1.1.0", "evp_bytestokey": "^1.0.3", "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "safe-buffer": "^5.0.1", + "timing-safe-equal": "^1.0.0" }, "devDependencies": { "standard": "^9.0.0", diff --git a/scripts/populateFixtures.js b/scripts/populateFixtures.js index e202f19..fed51fb 100644 --- a/scripts/populateFixtures.js +++ b/scripts/populateFixtures.js @@ -1,25 +1,25 @@ -var modes = require('./modes/list.json') -var fixtures = require('./test/fixtures.json') +var modes = require('../modes/list.json') +var fixtures = require('../test/fixtures.json') var crypto = require('crypto') -var types = ['aes-128-cfb1', 'aes-192-cfb1', 'aes-256-cfb1'] -var ebtk = require('./EVP_BytesToKey') +var types = ['aes-128-ccm', 'aes-192-ccm', 'aes-256-ccm'] +var ebtk = require('evp_bytestokey') var fs = require('fs') fixtures.forEach(function (fixture) { types.forEach(function (cipher) { - var suite = crypto.createCipher(cipher, new Buffer(fixture.password)) - var buf = new Buffer('') - buf = Buffer.concat([buf, suite.update(new Buffer(fixture.text))]) - buf = Buffer.concat([buf, suite.final()]) - fixture.results.ciphers[cipher] = buf.toString('hex') - if (modes[cipher].mode === 'ECB') { - return - } - var suite2 = crypto.createCipheriv(cipher, ebtk(crypto, fixture.password, modes[cipher].key).key, new Buffer(fixture.iv, 'hex')) - var buf2 = new Buffer('') - buf2 = Buffer.concat([buf2, suite2.update(new Buffer(fixture.text))]) - buf2 = Buffer.concat([buf2, suite2.final()]) + var suite2 = crypto.createCipheriv(cipher, ebtk(fixture.password, false, modes[cipher].key).key, new Buffer(fixture.iv, 'hex').slice(0, 12), { + authTagLength: 16 + }) + var text = Buffer.from(fixture.text) + var aad = Buffer.from(fixture.aad, 'hex') + console.log('aad', aad) + suite2.setAAD(aad, { + plaintextLength: text.length + }) + var buf2 = suite2.update(text) + suite2.final() fixture.results.cipherivs[cipher] = buf2.toString('hex') + fixture.authtag[cipher] = suite2.getAuthTag().toString('hex') }) }) fs.writeFileSync('./test/fixturesNew.json', JSON.stringify(fixtures, false, 4)) diff --git a/test/fixtures.json b/test/fixtures.json index 48b9841..87bf25a 100644 --- a/test/fixtures.json +++ b/test/fixtures.json @@ -54,14 +54,20 @@ "aes-256-cfb8": "9ea3993b", "aes-128-cfb1": "fb9d59cd", "aes-192-cfb1": "5928ce49", - "aes-256-cfb1": "e77b9555" + "aes-256-cfb1": "e77b9555", + "aes-128-ccm": "93cc226c", + "aes-192-ccm": "2f9b9215", + "aes-256-ccm": "9af05f4b" } }, "aad": "calvin", "authtag": { "aes-128-gcm": "cd9752d7719746f5aecdb2086421a890", "aes-192-gcm": "5f12847627262e0503eed9b26ec31d7e", - "aes-256-gcm": "1405b12c87d1a694e742c97f0e1336bb" + "aes-256-gcm": "1405b12c87d1a694e742c97f0e1336bb", + "aes-128-ccm": "0ce74a015e02fded98da24645649149e", + "aes-192-ccm": "de39e6112baa829e54bebb9113bf62aa", + "aes-256-ccm": "a66d726ffc054eff42788473ee9c532a" } }, { @@ -119,14 +125,20 @@ "aes-256-cfb8": "83904729f4ee79e04a931d3fd9f44b33092471a7c5818baf2910dd354a59eb218aca0d1595ae0c5f10e8648bbbe16fff6f84b0887b9291d3c688085b19ea736766b8d9fe1393fa5a234efdbe6223e6e00d460950c877726e90529a611c922bf94df399560f0528dc848332a60322ead63ef085359e325aebd71d63c80d000d72856472ff5ff1194740e47dda13e6b8c9330ed7688013a084937ecbb2dd0e942751d16951b12970d4336a2eed5bfea09a89c208bd57322c47ccee88cad39a69b2a9c5847c6f8999376c6c5b57790aca99f9e413b82aa5229a617babb57a37b750f38ac2d9f5127d97b3d2902b59e667273ec34dd9a51988e3210ce9217f2d02ceec3c5bc3e5d47ba5ff3cdd3499ddfcd348a9cfd9551d4eeaa55309ba90fb4e3c79419bf94861c70a2f2ed76d7e19258b935fc691858b6ef607e076ef4e6c6f2e82f50231a23b4fddb56640c5db8b278e6dbfb5220862b972d60bc2087867c6c9cdc2a25085a320ae4eee5829c31cb6f558a28b134e6af5839411e818e6f8ce1bf7cf66b2a3ed9cb4b435d043951158670f61ee601da6c2200a6f9ff7dea53b5ed4f0a806f14258f517073cedfa3fb581beb7a56ef4f3c466cd28f4fff7a814e92555acee0ada4475dbc8b4e246ee17aeb291e100ea5e5379fbb199e158b986dcbe375b0f2ff21a168d09760fd24f8fef08a6b591bc828c337f76568f17f11ba7dc48bf3379f84e5d6c2681bf2f60add2c3e1def3de322c88ad7e68e68ba377c899bd6099b3578f72c681198d1454eb6924fb41f069a151", "aes-128-cfb1": "0439ff30298fdadbf67a55a110dcec5d02dcaeccf9f03538879aaf861da5b8741a1f091a1c92150722341c1a58b03036507741c1f958a3c78d9bbbd9e85ab637e6a2c678547e7f1504144099a631ca87b4f855f01d85af2475f4f86a29a3f54ad57911b4d824878f067f800954c2d8a29a7399d7ded4ddca1f86fbeecb720311dc13952266ccf92a986c1a4cbc05d9b8aa69da3b1ba3a48fbb5131cbbbeb03cf9510c624ac913c9c915bb30f58825ef0602c803dbee9b87aaa5decec5460d77c9c81395b179bcaf9b1385f15f48bcd0eb607c004e88d277062dfcce9798e1a506817edad4294580d3036196df3c39f8194590c5be26536cec83f7591422029ca9b4347114bdd96472f9aea47dac9e27577ca328c42dae07e58e23c8ad5040095ff978e14ec04cd36baccf94c99e7b363bbd2c609ec1d756b01aff0efbd92b519bafd8d83b19f91c8e4abee0a23999fac373b478059b34077bc08bf3004232134b9af64d87e152922e28157f2abb2629e328e635f6122208123a97be602e71a68a2d9385b81e66bf05cecaabeb38232ad8b0a681e541d515d08fe9228f968ac843c5cf89113bda2c6d195ff33c322dc12f4177443f5a666f5192119576bd9ef0d80675a9b678a2c36be788518c43d871516d9ec84b2bd8ca3d5cf9e4f489efb0b35c87063b2c28fc54cbc43dc6c8f6dba3f79e157fe1c94a7a8201437d9ec33be49342337f4ba20177d7dc88893ed62b2bcb5ff16aea8a9c5ce7224272108622138638f95808cc8af2181e567f9165f5eab25bcf578cc5f", "aes-192-cfb1": "23cd583203fedc69777da0e8033ce5860fcd73b633a090f1401b42c615a280a4eaefb8ed2f62fcebd738a669b3ebb25c6a1b867c29fe2508d621686aca43bfe497c7d642976fe26693ba17911e7a4a3cc61c03f177cd67fe7fd49dbfb57aa9e07190652ce2ee745cc79f3403513b58d513b80f9653ad34863566323c8e1a6e2e1c0d42ada8dd423d516d168e7a6a958fb9f8a1248f7a05cff32e1d99986805a4ee4e822c9155a4b991c3a06e73f3c8222416f84d324e88e5fcfd1f6f0fcc5483462573e4ef80e4e3c28e412aa5c25f8ed950c18638fc1f26e2b8b71aa4d006fc8d8578979b5e87a3aed13a4e0507b37c31412871d5233c9539d5327e0fb0f4df5a77acde2071f8e1384a53b0c081d3271a6a192452219987cbce3266abcf672bc29d1ab560acf8d40053f9a47286fb0dd33d3a7491b3073afc751609bfbb8e930f113f92e5a373b85ad156829e4c2031df9278a47d5e857eed324c5827adade949628149fe2824cedbf6d221d4cb5ff303acf0334db833b8455e083b86bc215fa60f37268737af3bb28b76174353e3e80e8d2f3e03c4f8bba3ee28841540411ba2a203cb3329c937fd1130b6110b678255c07dcf1a3f5ae3817e0fea925aad7e089a2165031a383759bb4aaa447c4e0984526e28e3823c9915fae4d1a80d9c3c70f4fd145513160411616caa0e5d87e50a471a91a1c3edb7fd2a5cf586c358cf8c70766c3ea6b21abafaa438c6cd150384361fa97a39fecca9f71650c1dbec6e6a813067c8cc1b94aafc28e07cd8fb2c8cd21c0d3ee215", - "aes-256-cfb1": "feb3b856206c919dff35a5c10747c4541525eb3acfceaac5e3142abfd62aa83fd73c4b272d848b5dd29481ef806587980b7d37d2f4734804e55264fa0086c38cfa189d93aacf5f02c22b7660f813bae8ab5351ec7b43d71d7d2b21292c59e5eb59bf49e1e00d97e91dfb78ce579c25a8f5787cdeb51a8669f01f8ab8477a384131fb1294d2a7ab12aa7ff6631afa54c4c84d8c1942e46af4905d28d6c44ffd36c82bad4a0fcb8647922d5c557882c9178d97cf231d686a49871697daf44f01096f0f67f8524086d1d5092a9bdc9c626889ee596a8f14f27abb4400d426515fbcdd20e846b80cba07d3cee03aa1363f062a8b8a8bdbb12a8a49561aa221a6e81ac6cb22354e636a3385ef7bb35dac3894b91e62da576dd903029fbd4098533d341266bd7f10c9fda5c3b965a3f83dbf0053b0f3a6fc810074b92552443c06f04fb5235031a68a43ac856cf32549a447c84e370c306c2ae1a98851ead258918900f7321ab4aec78fe68b6ec2a19e3f2d71194443f227ddede56f91c1fee8db8040f99f04562edf5bb65967b223cae4423472d1a8d981e3ef9543eeb00af54eeac535f01e135d47bee122876b6f1f0aab9456360aa604dcd5732dfa946c196b60da7fcd4fed4fc0a110dd3ca7fab0ba711d4e679e59206968ecdc8e8d52af897acf1b1117052513ef4734c6dc320681472087b0d94f6b0e6eadd0b60e5e6733b28fef0d120c27cc2013c4df23b94ee2135ae688f23031c44a1893687c18afc457d1a46a56295c4dced26afd9556bae8cddede206011f3e94d" + "aes-256-cfb1": "feb3b856206c919dff35a5c10747c4541525eb3acfceaac5e3142abfd62aa83fd73c4b272d848b5dd29481ef806587980b7d37d2f4734804e55264fa0086c38cfa189d93aacf5f02c22b7660f813bae8ab5351ec7b43d71d7d2b21292c59e5eb59bf49e1e00d97e91dfb78ce579c25a8f5787cdeb51a8669f01f8ab8477a384131fb1294d2a7ab12aa7ff6631afa54c4c84d8c1942e46af4905d28d6c44ffd36c82bad4a0fcb8647922d5c557882c9178d97cf231d686a49871697daf44f01096f0f67f8524086d1d5092a9bdc9c626889ee596a8f14f27abb4400d426515fbcdd20e846b80cba07d3cee03aa1363f062a8b8a8bdbb12a8a49561aa221a6e81ac6cb22354e636a3385ef7bb35dac3894b91e62da576dd903029fbd4098533d341266bd7f10c9fda5c3b965a3f83dbf0053b0f3a6fc810074b92552443c06f04fb5235031a68a43ac856cf32549a447c84e370c306c2ae1a98851ead258918900f7321ab4aec78fe68b6ec2a19e3f2d71194443f227ddede56f91c1fee8db8040f99f04562edf5bb65967b223cae4423472d1a8d981e3ef9543eeb00af54eeac535f01e135d47bee122876b6f1f0aab9456360aa604dcd5732dfa946c196b60da7fcd4fed4fc0a110dd3ca7fab0ba711d4e679e59206968ecdc8e8d52af897acf1b1117052513ef4734c6dc320681472087b0d94f6b0e6eadd0b60e5e6733b28fef0d120c27cc2013c4df23b94ee2135ae688f23031c44a1893687c18afc457d1a46a56295c4dced26afd9556bae8cddede206011f3e94d", + "aes-128-ccm": "b7f09b7d95d0ea81d5a14d217febf00a14b459ed10e1cb7abf9e3d2026b0be90f4b0d02602dedb949cadf78e511ee89ff3b260a5e5253c007b25a1a2331883c7e3d3baa029d64deef02a9202ec1265db94c2841c738af353171280564a6b396dd9eb1e8e63a7bd6fd7cb8d827d72bea372a0d58531946b714336b1ecdba17c99307e42f1c9cab1d3b461b15d59f2dcbd5fd507a141fb54cb52981b17ff2720c27fe3c72a516524938f9fde1d2f8d28bad766e1d752603d2589f29688b416334ec89b2daefe38a039e30b4140ca2a4f60d40722e2dd28c626e504567d339d82dbc452560874f2e4c894a1cfb64c6818d6a767ecfd50cc55cf4d1a2ebda7abe91561aff65ccd9147685f7fa4e6c8c3ddbc63dc7bb811622512516cbe7e884c89b22ea8454252dd9a8aabb39154ea12a03e81ddae3597fa20804196799f12ccb7045fb05dcff5e1aac01870d6988495d5d78909546c78be88cbdebbf98c70f5989f254a24d836f64aaff409e9c37fb8df7e639ee4b2957df2d38e6571c1abfec7ad41110ea07c3a5dec50974775512fcde31fa235c24c8d7fe537b985f00456b5d36ad04f32d269bed659d0cbdd913ad4cb575409d388714867288279b727d38f647161596d24118a00ab5f74e9b8aeaaba35bab7db6a23a9b2e1b4706e0815b633be751d2ea96add762a1e20c6388f6a97fb9fa2b1300a0736980ab662752fa776b711aed62a98dd8f15b83a19c7d333eec6f3b9fffb328848a758d97d6a5a8d549c71c65d6599a9ab7817091ecd22264b25e364cd1b946c", + "aes-192-ccm": "bb072722a99720d23cc7da4a4f4ecd8fa2bc8db2e684bc91c7580ab3f98354419cb39e045b19df6af684eec37bfbfd30dbc8ba95fa0f0425c65b49adfb8a241947b5e57cb94e9799a2d2233f5f870db50a9f8040992c8531f518464167d2383c9de40f00d3aa9e8b9b8cd2afcf1855eceed2955bbe5ffc1ba63ab63bc1550e24e0240f08af80d33d79b33e2a8923c192cec9f77368189c0cc29b61261fff8e4c35ce081677d456b55dc321dc54819b62f507562fbfb64d538298ea4c64b16cac729473430ab27a2dd7e1440f1d7011d1767ca5adba8cabf542bc22cb5876e12ed5a5399a3a576526c4833104f703a96dbe1c871048fe03fb236d976d02554cfc77ea5b05a89f125946627f39353737628cff36f473a505f905ca36b443982eb00641b90c3449a1e5feb7be3afbd0e820359d184940d3a166ceb112d426f7cba936caf708178060e29f6fd5c4c7fddb08b5fbf29800ed353ccac732eb1d1feba1e726afa5cb5382d95554a8f7ba4f2bd9d48d81d7de30332f2bf727014d433e4c4258e142bf712666d29b702df8c3030adfbde1bd64f49f06f08e9c6926c5b48ed495d31fbe21004f70d3220716a28c1aa39faf8c6128ef146ff787f00692a14898817949c8178e46e70e2211f81bb4cb4e31456af0d6d568a74124f2dd51694c5328e49d1a8886997ae916bf3f980d5a26f641632147f1772ff5e665107ef80f7fa5e6dec80be1b22a5fd15ea98fc30e5774634a829e135277d43a79aab80318b33b365add83df8831c0080fb441736fe694c7bffb87c9", + "aes-256-ccm": "9dfdb41083bdfc12980a05415abfa95c25dac5530a751d4b630db4b74f9a9227cfa3922fe46774f29e3033eed41666e12d5f7b12bc525449a03e33b6e8c7cfe94a234daff97aa3b4f7095b33feda08b4a11fb5d305458130290fb0bfeb3ee9a47828536c1f9a93c46eeb01a6526213c8687d8ca59ed67f75894671a5813aef5df0ec65cec39b072a67494b1fe9cc556a318a67a2dd33f2efbe9ffc70ee16d0b4e9edeba4cc8aadbbe4164591e23c7e781fd8d88a7cea4c22b183012ae0d6a91403d656e5707a516b692b1387636a6dd49d16faab28ff00a067b4de941177f205ec65d285e34efa04029e9ac7d47d82e4e074006bf5a66b06f5fab4357838d7502329e739adb5d8161f82c374161a88cbb6d0eaf132346d5a44d0e9b1204bbf41beb239b80bb8801aa1e357c43c09dcc4cdf6a5a97a7f241030b05500aaa34310ba8fa222025757056f8897e8b256afbdd51ad06405c2a3e4bbf7f68864f52cb497eb4308a69f2f0a93689c691c3f64f12f2905a335dbeae9c0226b78d638e9ab9289cae045ec79629d3001faabbad01656ddeb29a7b20123669b26ceb9ff98d0fa21f326415f2f8987700211f9c62f0f6c4400eae8a342c53d08adf3b0f225e89e1d2c5b37c45031fea1a306065f2aaeefa400dc7a8510a0167d576a379628583eba3e501230a75411707a53b74a68568e6bfc9cbd956e8c1687bbd9f24940e5702a5ee7d377eea9e7db2658ffd90c818db95ffc744492018b6c84bf33e830de578d5e99708862bd7cfc033c28295fe5a1cdbb39ef7109" } }, "aad": "fdfe32b59b3d2d2b85dfbb680babe590ec162058988561b0a869e58505df", "authtag": { "aes-128-gcm": "f856f31f89b1330659c23002e06d73e7", "aes-192-gcm": "a149e211df65731305f61762107d9c1c", - "aes-256-gcm": "69bb4d3b34632ec108e0f6d41e010aa5" + "aes-256-gcm": "69bb4d3b34632ec108e0f6d41e010aa5", + "aes-128-ccm": "1a5cfd7ec2fdd9eac6a308926590e73b", + "aes-192-ccm": "572e5627935201d648e0d9e36c55ff70", + "aes-256-ccm": "71d309130ce937252c173b871703e8fa" } }, { @@ -184,14 +196,20 @@ "aes-256-cfb8": "9285862e89b9", "aes-128-cfb1": "15450661a91b", "aes-192-cfb1": "63667c3b3500", - "aes-256-cfb1": "a7d8bae0ee48" + "aes-256-cfb1": "a7d8bae0ee48", + "aes-128-ccm": "be67f6cea2ba", + "aes-192-ccm": "fb11d7741b01", + "aes-256-ccm": "27adb7a4a50a" } }, "aad": "48221a601f6da68625580fa7d56fb44f", "authtag": { "aes-128-gcm": "4b733a96b107050c93acdcbb4df4315a", "aes-192-gcm": "14eed33237b36219c66cfcba504da0a5", - "aes-256-gcm": "f29edfbedf6fd640075b091c6eddd774" + "aes-256-gcm": "f29edfbedf6fd640075b091c6eddd774", + "aes-128-ccm": "2e7fe5cffc2532213515b58b304ae4e5", + "aes-192-ccm": "c14258666aed9a240ca7e49527c82344", + "aes-256-ccm": "fd75caf3c93935ded5f6c73a38d03136" } }, { @@ -249,14 +267,20 @@ "aes-256-cfb8": "7cb057cdf20b800ea9c67a17a51015e7", "aes-128-cfb1": "4d35b5511e8aff571961faa4407e8f9b", "aes-192-cfb1": "97b3cf0ad36abe8c78d59e2c380f29a0", - "aes-256-cfb1": "567d7375364237bf9a0982678104fbc2" + "aes-256-cfb1": "567d7375364237bf9a0982678104fbc2", + "aes-128-ccm": "c1d86e8831dfdf8d0bdb470de45d1ae7", + "aes-192-ccm": "3b03ee096e02c2709a6f69b56870c339", + "aes-256-ccm": "425b0f1fa33230b5943b267fac7c52ea" } }, "aad": "f6bf5b6bb5ee1b", "authtag": { "aes-128-gcm": "a1b6a1eb59fa46b25b29be41ea2ccee8", "aes-192-gcm": "f7151ce9217f96f6472caa08677eaa8c", - "aes-256-gcm": "94765e8761e86f826fce4202a96103a9" + "aes-256-gcm": "94765e8761e86f826fce4202a96103a9", + "aes-128-ccm": "1fec9c27122e8b392455a17a875cd613", + "aes-192-ccm": "ae958d239453e755dd96754c75723306", + "aes-256-ccm": "1825984f8a6b7a76ce3beca8314f0463" } }, { @@ -314,14 +338,20 @@ "aes-256-cfb8": "685c731c42ebc72bd7f383800d669b3925", "aes-128-cfb1": "4949e647f5e8771bc6c5b1d6819a870d3c", "aes-192-cfb1": "5adc60d434310dc056f4ed3be5ce833126", - "aes-256-cfb1": "7ae6cb7a0d6b809c74c51d64d9e27a73e2" + "aes-256-cfb1": "7ae6cb7a0d6b809c74c51d64d9e27a73e2", + "aes-128-ccm": "bca3abbecaec37668d92dc409a50a7ac86", + "aes-192-ccm": "d19d2cd479783c0c41cc03fce458ac4d86", + "aes-256-ccm": "e591c145cb0365f8086a3a62bf37f499b5" } }, "aad": "950d79f5d8481ba511069b6444cb4f85faebe54c84a3dd89b0b1aa9e78ca0a7824309d423af773893084482db47ee132ade0981ca1e3a46868ada087fab5f60d87", "authtag": { "aes-128-gcm": "2fc30ffae7130b2d90d9ae83c5e1c50b", "aes-192-gcm": "c33b5960ba9a6d0078f3fa52089d88eb", - "aes-256-gcm": "fbc18b1cdb10be8eb28bf4d4a76b1991" + "aes-256-gcm": "fbc18b1cdb10be8eb28bf4d4a76b1991", + "aes-128-ccm": "2e2931d00b31c97714deaa64ec81ffd0", + "aes-192-ccm": "73992facf93c38977266a89a5959a4fc", + "aes-256-ccm": "6ea26309661e709d5c18abc8b2fb3368" } }, { @@ -379,14 +409,20 @@ "aes-256-cfb8": "247d8b1932ec6e8714a8a3a77b7396", "aes-128-cfb1": "c2caf14db9b96e64ff9f48515c2aa8", "aes-192-cfb1": "4a6c8428e61ac496b26c5ad0deb89c", - "aes-256-cfb1": "3f3492cb1b18c962ea94da3bc5cf53" + "aes-256-cfb1": "3f3492cb1b18c962ea94da3bc5cf53", + "aes-128-ccm": "b5b023edd258e44e62825c81139387", + "aes-192-ccm": "e461d8e472b229f0ef1e7dae144413", + "aes-256-ccm": "da065b0a98847f51dadca9a824401a" } }, "aad": "25f5dec376996cd7bea422bb", "authtag": { "aes-128-gcm": "9b39a1c53e5ec8b327a353375bd2daf6", "aes-192-gcm": "f073f0a06ca07c0409ed09b43abe77a6", - "aes-256-gcm": "acd7ced603ce6be2ff7020587dbad6cb" + "aes-256-gcm": "acd7ced603ce6be2ff7020587dbad6cb", + "aes-128-ccm": "ccdb0e265a17a012262314c22465edce", + "aes-192-ccm": "b78e6d3400bfc8f74a654082e73da61c", + "aes-256-ccm": "ce682b44dea59f5b541823fb1407b1e2" } }, { @@ -444,14 +480,20 @@ "aes-256-cfb8": "adb18be54fdd842ffe42548e8d4c61f6a0b1865f13faa8093d44750e555cda0d8f09dde86270ddec8a252e229b8ee5c17621541320ec6079a30e15eaf6474595c4dfb9384fa0100c89f8099729cb656805663ce5f35c5cd40fcdaedb09c82da69862b41ecca94573d8edc5c620e19278dbbc73d822e0094116bd4dcb8bfe1f2f2a1cf4ee9545c9f18aad5ad26b3344533d660db09c836aa02ce258d5a0db2d2c52246fe65a2e2528257e96cc211fda09494cc77bab48dbbefa17cf224d819d65de554941b3d75c970c1e3a2a705c8029b7bd4591312ad4c458e37a791ad359bbf686d7e1f086704889ea69a597c468620d524551f478c1878b0043289cbb45e3643cd7ef57383f5e1725fc07a12e294d550455ee3c51e36b9a33c4900ac28e02fddb46103c9a45797c4a937de9c850a9fdd37db2a42ae0342ec0b5ae2af8e7de72f389b1d25b174de856b52d94f9af1f6c723c0512b5ccde503e410e1d1954547810950f5f8770bbcf4563d67d0cf085e7ce0ebe927e0fa3c4d88feb4857264bc68a21245bfc59f369ab99120d0563469fc088c09423b10fa083cef2418d9b4c71247112b091a5b3f81b11061d9d8adb66db9ae58ea05b60d7ab96566c1048c5ae0c0b8ded4d9b80e1345af5d4391d4e7970d36e1532852e9b0bba4ccd7c16c5f3d1fbe18fbafec4d66d7f540d750e4163ee500ae3b3d98be44f26622d0d40f8af3473d781efc5536d20a5eef44314a3b074e86d1888272fc647ea519522a6b6f13c2bcc674fba481b58c74efad36754e5c5d3ef344f3098aba9f19503d933fe4f5ee00a53a3d83b5eada80352793ea5db3898bf80c2bc2a3ad1d08cd46f61708c4f50d331e679f1d6d833cd17b5eed201cf73a4d6f557c1fbb174b0f8bf3cf2281f547133bda34954cec82e1aab4bbfdf0ab280debc7847633bbb84b8e1c1b74325a2932c99637ad32fda1b393cd557eb8cfad1220dc5b081b809d3b15c15aa48be32da9e65de4835df07844b3ed0f2ede9b25e940e38fbd768ecc2f7a825a6e146d27b9d79c6e46944468d9e70b25ac1a6b1c4bd92b6d30d2c3a58be1b1cf5fbf87f0e74b27dac05de25c159dc623cefcbee95af5341b1457b7e9e7e6005489000bd23ccfea096bb7241014140a1c20bf5a0e0eecd4e25096c1e46fa1f688677404c75488c988027dcbdb6c30faa677b3fc3686c52557252166b706c9385021636d5311de02984f666d1d3793b171e527c13123de2c53e870b62f7074556766f33be30f7560e68aa5b5b94d165ed0f9677ca4d42f615da5a666e32d3f33a9a3ed29c7ac26b99d5e08a090f1fa668a31af9435698a2df6d90794d5f438838cc79029caecf63b81211168ee29117c588f31f3bfa53ec5e3605206cdf7e1ed8418270e604632c1e079e4282ccd989fbab719a26f23e5917f2dfbed61e7e8c9788ed3cbf8e4b29c0010decae7b207fa8b4b66a50c11605d756c2af721c0cf7bb89627ae015f6b39e4bfd4d5fdcf85d29cfda44df04cd41e353f5e813d5c2ec4ef337847924719f979210399eef0c0b1d9ebc519fa180ccce3f2e8970142127c8dbc4b60a90f879c2bab7815364d22de59be6d6cb2c11c6b4f5a4ca03e366d805c3cc800aee819cd419c6b848fa9eef13598a2f12dd42777e8c0fa1db98ae926c9969598592e818d3ec3dc439aa284c01066ac880c5495a6e7a4d3d0525e37b8aec5b104a6309f801ecf71aff6bf20d2ca79634917ba5b8d32e8ac598085073ded0e6e4595c425397a9bd908e538fbd1f78eb012f053d065f7a71b92e1a8e4e2fc968e8df4cad9b0ce98a09daaac4331328cc9293cecdc2c820bef962979e16c2d7b72bd24735b8a8009a635aaa1c58f7e2c6d7ddba444a5012f22985b5c4f20ae4f5a01e3f5350141e59e7b0e1050c313a40d2c4ca0485c4341c44aef138881c853afea749923a9ed202c0c00c9d56d9e34064ee48b23ac577739ede22c19b34b4ee8da13c07919a97a2ab0c04633d0047797d53d9e154abcb8eef9aa75fe75975a6b738d40e975e398496385e89834f7916d82de643ed50f7f19bd8c60214f00f81d5797f210f4f6c046bed9b8da6531a6b0d20be4271d87d66f350ac7855dad49f4ea198fb6791af956cd71be4eea2cc0f61bf008054e5f5c9d4b0faeba776eb2f9e5df9a5380c059ab109d71c6f307896ea388a3187435ef7186f1dafaf900ed70ff0922441c5fe83183b85fa4bbf597fb0fa261dd8dcd139a390e1a51f44a4804b7231f85474399d25dc7b7fce12344d743a17a7f747b44b1cbf247ec1dc2c189767f8979aebb7cc8e29e1b5b251363160bb6a8e854d4e18882a3ce3172728069217a2e2d684d9bfa5f2ed0809125121b34b14534d4fb80b6b4dcb17a27631bf3bbce2d251019a9b5297f0f22987ffd91c8acd1857a4c3f2378f87faf8043c3a851722eb027291ac070c2fa55a8cde602a62f93e8f921975674308f5d9e54c34eacb09b6448c5277cbc947826567e7149f9b90cd25d46c9528a9d7a2147c7dce1617c1071ad0c897615f0939f955a44d1bd85d067dce7d89e28fab6aefd210a4ce39df5dddae46faaefc97899ba385a42ec5a14c3d044aedce07ff5235b54e61a938546d63130b25d57009bea0b58e8e477faef60d84628496eb929c2ddc59bf39e1d0262d5e9289c2b3fdccbbdd6996042e6ef039805fa7b237d34d7dd2a63d7e3a623aac39c7dccf82a9f5fe90e26569cc5483a2d03f09a372b9dce0e3ff339f1931f2c1afe6a5040d44bde5f0077af80f7172154b7011b1359029c1d94e83b804343c56b29daa13cf74dce90ec4d5b6c1d563c85dd266d130f9b72eea5f80d8b996c0aeb3a95b4dfdb53e71979243f74a65db202da897a2bd01986847f7f656e4f96ade8216e06357bf4972d8420e304bca1cc179d4de79de133bb3c8130194716986c9aba7a15054b8402182588fa32fddd17bdceae29c8344dfafcbcf0c612a2c7a626935d172ef9380905cbf52d3cb570be39fbbd456dffd0d425df7e5de37ebc3e89484b2b61bdea9b5cbd2d4c0b00444057d4380367c8ca1bc64469db299567234cb7681d96fc9ab202db2cf1b1c7869a63d6b339d3b217107e63bd7b086ee5882e0f741d46b1e155b84087c7bb8d7922c3bc3917bb18c894b8dcbdcee10bd6b9df5dcee22760b2c0f40cf7842c99841f55d1effcffb6b24700338c8343b4305ca985018d7fd1ba2591a782ad98ca34cd536ef78e61c636da3309b4372de0e445153e6af0277bab15ed6d59a9930c06d9f4ca05e4e10d3fe9735e63d5b045ffa56c2df6c0b329f1716ca75424fbaa552e3b6f74ad6817923e8ff0d1d5932896a8dc90d6d70f591b9959ec699b8ab7945753cfaab6644273cfbba78fd828292dba1bfbadbd15b6a5e67c7e51f2d8e7ef320b65fd854e6a6cc506492adc9e9f8a5f0d5075d36ed30192bbf9757b25dccd1f965ccd132adc0304e7465fee40e839cbf2e88b49dd3a5e65604f0a29a605d71aa187c20f26c9c28088a71f6501e69128953a80dd52a94fa4834010085eba8e3a472d2a698c95c7de289d1b02efdaffeb2fc539b717f8986f8cd0434547d4abe7f3b2af2f2d99db376983fc84044aa7f032b875a207d61ba2ca25daad7b5bdae79f3ee82d9af4c76e54dd2b6a68c35f9b92cb168e75bebcd7a6f759fc1d31ee3e6205b9a85facfd00fb138940e69fc283c2eaba2a8fec4b5beebee1ca6e5c7c023048e55e600aa3bf8d2dde5b7e605f404ed91810381ea6dde76e89325ccf4667925720f45d77ea17a87d5b126373af9e631a89e66a6f25bc8237ffb17de11ac6e10b333e72f2ce51e7363885bcf88a8a7759be864252fa4df02291c8fd9e5cddc5d1c6a5349f87298370f629bb6ceb7205bfe90f0866ce303312cf1250468e579243ac36b41ee0e4f15b12988a3af8df32998101771af448e24a8f01f3558554cad4a357042d005353753e1017ca418566440ee1cc63da0800aa47778864d5c884729bdfa8c40357a5da20f55de6575cfa3f92b69f17e7a4875bf1b3af2dffd1327a6d534a1eb546f501954a0c79d4dcf6148533e982e8ca409a8846c6aba008b0cef674cf367ea732aad0ef467ba61d89b2b2904dca7f9409322786ce84cc4e99bceab5de5895ccc89ed5e42be7c300b4a338b6634778902", "aes-128-cfb1": "9ac3ffc130741e1008dbe579131c9f6425663d516a26c1858bd11c90eefc31f698a8d4887f13112f1466a7a640ab2073fe53d4917d650e382dac5e3f1b3c1af3472074855bef815e1ea621a9c337d5a7cf73475bec1e0974ec2337d50dfa27ecfca1bbfa391d80404039289ed6eb049cbfe5f69062ef98b9174b2091b98d92a8172ff38ed2e8b44d0a4c6f6f0dfc022990814f3cbbd71a7b53d32decd1a2fa4663ce2559a60c50235262a14f1d580ad07840cef8b443498f342daba4f23539af294bbbd9c35c6d6350de269198f90b1ad232488a1a85b787724e05692cd5703068a36732bb35923d8e2522faa4000b98987e182fb74dc6adee584b0ce0a79a48b1dc1843b1e3071a41fcdc09f53e5f0e426655464c7e96ace867b5d1f5870c94ed9a4417c93c917aa531b6905b0bc13453f0c4ba6414acdb5eb4362c647570d317667071e5e81348075e3a69286f48bdb8e1fce8931854ef817873fcfd11fcc73510d845232a8d7c465232e5367d27cdd8fe69a119f8cbd5ccf5c55405fc489e8db3889e87f2f346209f2c9bc1817feea79d69743a3f23afc39a0ad011b3e0c7bcecd369416a90385936f3ed5bb8e77c8e224409f1a28f5bbc486d66b430e9413dc03199fa58936ef5e953563f41ed7a9cd7e67e47a716edfc7e723786dc0fe0c7930e60a4c3008d2e0e608ee103ee24c16d6b5d8877fc0b794efc4de58cde0ce4d2ef85e0ee3dc47faca3d4ad1dcdf1fe26735e4cfdb6d69b223f42850c62e94c844de95eada2ea84091603a6536a431e2574c37c3c8f85d6048e2fa29b7683afe75c3acab595245f3091a195d404c868e72dd2139648abe2dc9ed2739e83312cdb01de79095e685f887394c11e7a4d85f3f32c889a6121b400e34f7739d3e8b6c59e4c9324ab818053e8f7a92449170f0742be940458365a4bc3c113066b299bda92b415a2a3c9093965f657ebb55c504d712cbb96bbaf42e0b6c5c20813653223ce2e47fa5b416da8ad2848b7daf0ec321a6fd99de8a4d5cb04035ca171f7fecc934985d326f911ab283d1f5102beb2ca79f161a47fbaaaa717805f78c5da3eb5af3b57ebc2e3726286cb17e764afb85a268427c474f10ee73c83c894786752e6355b0ecf8dc2076eb1f05a8ea1a545bdb7c8eda8543191b62aff517cfb67b6c678b8f4f482599e0c02cc7458b6a799db28c4bfcbefe103ad0dd882e318744f22d121cc234235ec2ba3d13081e0211e9070a8d125fc164bceb7cfc0fea553ea0a59e41dbfcd5aa62c13859183bc8b2b459f34b93f71ee770d862356849498c1a264630f5d578ee4b4ea99db6b9cd199e709c7ab6d3ea080e3e85a4294ecabacf857d0afb9771b6d5f8ea0dcb7410f87066c1bcfb36cd435c32eb202973b143ac4305ebed431cfc1940a49a9865a791eae5f346705ed2fe6efc63adc46ff640cf80a94961d33effdbfd747fc3f6b9d05c45f9400b9dae8e802379f15883033ee6a5626537b0c3195579ab243a8daefa19afe4306104b1c991884868decb7529bbafc3cfdaa724417b7e5cdd84f617c0e9f8f8276f3d689b5447963a53d047d814bc75bdf66cf876b83482ad5ae49b13282edaafe4a0d62e17c5e61d83b333fefd3f35fd7d395d84e4757bba12084d5b3b6a92babf646701bed9e227cbd82b6583577df42129f088543b9e143c14a69980b74cb3e7e8dce245cad33732355527617131c022277f5f9f685c475fb13cc760c94010ee135bdf6b1b2226e752cd570f31ed09133652d03183d211ed98f18cb88a9485106b77d6815f0681e643bfb57454b2622ca95a72e27d1e1018fe0ffac597badccb8b569babf02fcc8f38868bbaa680da7ba8757467352bbbf449b4fe349f9030f5c48dbe057fe4ea493df3521d229bbf4ad9ebcf2de3d4b3c52857834b3760c01bfa70d8cb978bd1e591c18560ebe18e78f920e70be450c61c3f2f3e6bca40798c7b10ebcbd97db8c7bb0f143745bf5df5796eaa1387087368279038e773c0094ccf008b6ce7adf19a61e19dc9ee74d9cd79dd2e84988e0324bc0e4b3ece50d7138a34fb03c3ae4542c1f69ed312cb0ee506fef320701ceb75030761833606dcffe7f76e9fbeb0d91b02dc2c77a7e50e17ee72c56c21172c183d7edb9d72223338b48a06402424bc70427703dc36ac05e50962a419758af34346374fe694c442f729aa0247904925e6349adac560102e22fcb2c791b2c63d654076074f1c833d2636bf2f319ef3d428af300882d954627d3ea783b367ad183015b3094e2dcde5283fc0c6f56f3db09f986af6108816b22fc54b79ec026ddfcdc8359228827e73a995068a521ffa52a083cac1e5cc0bf1939582bab288db532456c6526d33a635f4ace2e05a94e200469b2a73fce69d6a6e1579970b4aaad9b3d2c4acd6dd706d3b2056ef82c00f52067ef3de6e06189763639f7771e81dc89100f8d682f042e30d77783616930430d54ca259a86e423e9fb663ea2d53faa751ba40dbe15696320f0e2097ec32ccf9e20a06c189f2811aa4823584e8f5c97c31edb7bcc177083929cb7936485922df83da08ade065242f9768573c6adf8118551a3de47fb493c58e7def8dc988e36ea8c8c971d3a9695de2623b2b45396cb77783de1a7256c3462cfa6b5d8769e1f81da7cd01142a8a93f166d62e72a00586afaac8066a28ef1a57cabca3aa3416edd198ed276b66dcd90f8ce7a19bb7ab8412b2633a275d070642bbef22a1d42744b6bc7ea3a42db3fb1099f65ceb1c139189d38872b3acc310df268d7659cc09bcf250172109101d116e416d66022ca9f5e70e1968357e8f9ebb30d19b0c0b713166bd965a046eee5936b1b0e46d1219c7fbdf19bcb126a1d3cc51c02981656d44c80949d1329f2b9be57827e29f806e47698d96b66e55b6cd71b7cacf61b462f43aea151e2bc1f63749651c34c496585f1d196125fa83cfa3a125b854bfc45338664f8067c4b4418141fae8f30d008affc1ead19366f5ab14bd1860ccbcace222d52ca241e1a1de0791feb7626a105e1be8536b98b3907d4661e1615d2c56f95758f28e599bb4e34b8d2e5c56914bfdb94e653010b4ff620d65623ee33577d4144b5a542327984495e573174b0c6fe77c4c009d4c07f63b6b65845253d5884637cb68f44fbb1f49157e0974be6f8c24bdbabfa29afae184548ce61716f54e0da168b34ecef60035e42c6bda928256d24404d195c3046a66a82beb0023453866986f84c30042c77fd1049531a243e1fd875d2d8e6996e432911d40473269e075b2699b04ad7d100d9b3699de612e683f850fbe9b09179037e6c2fd0d65a51f25542e3cb4a4c699923ba7758033aaf83c4e676e41843c0990d863258a9fdd0070ae54fd83a06200ded35cf9c3db8f2aee74efa70827623fa7d4ce21b6129363344f9d30ac81311026153b65b40af82e252979ab6339b0909bc6d543e7408c9c2163cd1771baeaf6edd84f8bc762e4e630bca65058ae0a7b7a1f2f50cf8d07cbdf798a5c77aaf2ec661c8c6f3baa84d64c1a1aee478b7da922f09386ceef6b0c0e224529b766826e700090a6014542251c5697ff7f2caaf12d941dcc9330814ebc9a113e35b230c8ff3a1b20e64c2fc375cbf4af443f10c8f4afa44a3c189fa722a8186c5fc9dc6cd8af9f9dac5b242b5dddf7f7736234f609ce79f54b1ef51aa05cf27706f22975c4cb3dd522fe3eb176267bf428ed7b61f3d5dc7f32eeb0416fa393e25527c5516c45747d41699a70d2a43fab8bc9588a0f60a25b7ed140a72dc7dba0dffc7da9625f65755e15deb58d7b1af59416eab22f4c95eb07541cfd329854db079d449bafa1179c117d0684a5e8c2ede512bf8d010926dc21c63d1ea08eb7372dcbfe992867beadc5cc4dfaeac8b1e74659e6ae05ee3d98a3d76efe1053f865b032a43f067f1876197edc57a01e9caef529d7a83e923aced84e4a8f9fe9a7a70d346e051939cbb3e7b58867744dfe119240350853039c82fda6071bc839f599475d4d30c0fdd82795ebe25f537ef8bac980100509b38c3e66e799b858a8452cf7d1b9875b410d9f06064ba9422a77575d0833c799f0fa837e88e884dcdda8592e08e32ab658b9ff92e1866ac207ed4fed1b5d94a1c4b347e216883461029a934ab92f005715620a68cf044f0073be2", "aes-192-cfb1": "4fcd5b423adbdfc4966c971449a045db51c031a44b11439ebf26cc954348c942c131a95aa1687f00aec31f88cf0dca55e4305340ded0472242f77b2a98dafac517b8c616726be56af8764be5bb0a03e683b00f5f02e49880f964d0aac6e34db65e85d181a28ce2db9e1ca6b43bb450caac42c33706f312449b5544d62605df1064ac897415cefdb91d142638a4f20c3d56881ca77433b25daf57ea1a5662d892df1cbb6f8b665dd94bedf3b19f0872734482e9d88544c1eabe6959e35c5b5d49f6f0c942fb36bdd05ee43072adb484c14512a7b9e7e8d238daa0b930044249c43e3ee2b5ee96d9d537249641d5f37d2235946a1698ed724890b80c44c2a62c32ad69a73ebcf7110f55bbf048600092c8b7087bcba7752c4d799b766e9b77671f6f9e7a9a72088ad1d7102463a545b4545d8ad4136a65b589ad0f9b2f305576de2aa5f339033397b861f843c8471787b22b947c93a861bdf546ab997d12ed9ebd427908e32314ac5e116e79a00e0d0ce9f7ccaabfad96cc919cd9e30a3eb551ba90b47217ddff8f414db6bf4b868928ea3e2264172dd74ba9fc28fd301ce7d19e1dd68b6bdc2004ca7d1cfe99ba5346469a9a15f38f2ba2bf3b83046d2eb5cd822ab01410bfd13bd6cd6231eb5fab3ed68a840922d6ee7af458a11321233774821190abf68b43714b4d8ebb2bb8fb6c2be59f755de4d0c1383360cb8591f5a2f300461ed70c4fa5c21ad1c23c8118b48c9d8370fe2f849c9ab0302a60dcc1722e4388b5cc527f2b183253e3202feec32fbdee1fb9071f419a81f38358c515d0369d1755c9f85d5051646d8dde81254694122d01a5aaf25b957e87e569a93161394fa62cb161aace0da96d0eb75491476bc10d6aadac81890ba9be03337b5fb4fb8023e9a68e26e2f0607a990fc5b9e07cdaa16fea287298d44a84a9c9ef1c1e4107901e8be1398c8265c1081e7dc8bad8eeb01064b3f1ffe07357e61342c022b0e25e5df188c091d6bc7bee96a64be8d227c34fc88692b3295f85b0d8dac91844f98548befece965e465ec80009c3d3b515dc6b528ae5922a8637699f312f51deb6080a4262bb3d2eba40abf4375c6c7cdd5a033519a1e42a3ba63064227e309492ff447e8b4cfd645d2370f50feda1d6e23bd841b3c4ce92428660f251a158c59e93599ef3ae3def1358224c45afedab87d5da52d49fd456e828301f25a0e18ec56f5d7f729b3540d5cd0c16e4ccfb3cc6be975cf013f2a0d4b8e14d7b17b57a22645e5ac97da8ddb65e24e47dbe6aa8bf2832967f7e22a4334c634193cb07b275aad27d3fc282dc52504871b35751ec9d6e71ade719f1f5bb1320da1d7ea2e067876b30cc6be57ee80025caca1e2e5cbda3a165296f5d40ecfbd78142f79f1ecbf5bc1f40dc5d307a76da0f92b408d9db811ca43622ae1da368c7555da2b99484c0ae4d6db2d924f29ff68ac3276d65f32e878891e52b12a912e5b480658c1e2203c0469970a8f20b16758fc953ce139d40eec691c74875382e9dfd040fe8b67cb59c969aa24d2567329eb85727a33023644674fa9d1384dee8677c52f5cba8009199d06736d223e576668eb224a6daf5c4780a49c218070803455906069d2a00084d7aae22c9378c5b90f85ee0869d94bd75c736f5bd1d969d8ba4ca24ed39ad8ed74fbbb2d68867017b3c286bfdc67797d9b48bbd5c8506555d125facebb1c54544ab3d8a608a5f3f657b573b85f4e57ff9acac9f35b22207f1d431f4f2206dcbb959b4e73712f35f42bea03296014711cd788a7dbb8bfbf29537a146e09b65eff9953bbc4c6cc6245d9c364c930777eae3173d91744526ebad35163f491f55e53134fa79763b88fcb2b986c2ebe6396ece40c2fc5f14201588d2d8b16bf03a538fc7c7670f1afb7719a4202579f201c2873773f5bb3a36edc185ec3ec2205e96f5f8a54fd43148446c34d16aef0c2bea347316af16ba439e5b09bb8e13235dbb4d3cd609067d282738c99b1bb2afa0fb50538534341ae9ec839c5179f0eb4f05c4bb40265036132771cb589d5e3242199039d4f3fe82fe083660d67f7c90ea6362fc3005fa31f2da2226e0e196758176e3c654b7ae75e3fa8889cac474db30e6b1c84db0dec46e2a0444206cdd6cc2cf401d9b8ac85246644d947ba4766193e2536a7792a35447b064b80e3e597765043f3ee1b71813926f27342ad3afca285f14558daf23c76e125fbd4e97e785318c4a662738aab767e9d44bf70c05e78b70ddee2e7e2cd02690e6b4095165e4a5a1332f1de54f67418e0babe9d505beb5953516dbc84bd9581e6438ca664c2b4be1612b09882c6b156c69390865e89abc5213a1a9c55268b1450be7e848a1a8b55bd7b8d30563ef1ce65b37f21aaaae1b88d03e54940b612327ccbadf5d55b89e31e3ac0d8bdbb6a006fc2623fafeca22ca15e728b64233e8e8c4206c72fda462c02ccbf5c1b3bb2b69cc3153c55a9485d58dc281881ce9576794f323852eaf41efec9c7475dba7e2bb6c4c971ecb265f62dd1708f2eaf320836e3b92ecb2c99195fbb3d10dbc54aaaab632e3f8db21ac9eaefda4fc92c5b351705220d4c98eefd9da8ab225750e279e4a0fe6c0d8d833d837d7a919a06468093d3ab4d97a35fa520c2b3e5fe2f6739113828a55d523de8b47bfb1d4da6ad4d4f252d657ef6cdbb5cb7e72da215915b0dad5ca4a4f9d4b11d72d25dc38e9ce1caf944244387607523695119fcbfe83aeb28ee3ef3f3ad97d558eb1d9101044d644363fcdc36857c56df065c21a1b03aedc3217da1cd27d3e4c2242980845c8f81b3fd1595b16b9591af8efd0f69951ff4daee96a65010d21a731fce89d6c1f39bc264b14d72ec7e0e5babc61155422066d895e8dce14c07db72e24ec1aba51e3635c4bb98a6b47f4234803283da5b24df9ca7f8d0eb3aeed9e49a61b1f267db1f062d1410010421b8104e50469233958c5974ceb324cfc10df4517e64cf7778217a927e78de03017c1b1cf602b0d16be2d1a415e2d0fec08f40df2067155623b7b25bb9557e4865b1078998096feb334f1341332b1fad81c0f5b1cf51ee5e31214b3f93bd41075ecaaf976f0424e3d648763f9487420ffb2676405291c7aafafb0fb99a80e835eb286e079c6bd60dfc87153aaaa1be79254c2971c1f9c1f6e65fbbc6086ef4b25b390fd7ed08b9b39769b684767322da8377ecc957397310678099ec3fee3bf634c86238b262c7587da842882f43aebd2ac646a4d9f689ef8211b0ad443fdb1abb4e96510e239b84ed24b704fcea70aae21e1ae44a3f4f35f40d5339a2a6bbff49b9e48a0cbdb3152971da8deec5c16b55e65c29c2861a5420327c5903da0284cb9a7ce27f732b3f8aa92e39e79e4863437f403c205e5068989eedf0388011bdf2c0840f3bf11c9020ec612c6b7bf68f53d05d0cf1bf9f3db65a4538fb727dc805cb27e152e8debfd24a15c57d9a03c0201331cccb68c8c25847359eadea986afd362bb915a62ccf2735f0db6879b32c935ae7b032db10523af580ae64b1629dac13bec9e47a4207b3b968a4a6af0307ae1d5cd7aa823607dcd7184b11ec5a6a1eda2064f6b27ba454bac819ac4460314d2260e817edd537b14563f470d7df51f014b8ed4a8b22e1022a7ab563de27cfdd6aa8cd0289fff9e8946f2c456710857afda8eec65046e5600099e6b478865861480e658a5463a758fb88c15c9a98b73ea06647961c614ca52fe8f8d2f4cce6762ee54de7e2ba0fb79d4cd97c13f1bdfc125072d57d170b3cbe715c4e54dd75d59ad32d3645694e3e1e7b8c0595b37b61939a4b331e750cab84e3c7e7277dfd070da686d3ddc6e5c195e8ac0e5585635e92b43cf8c5a4cdf5fc1d63b668ec3bed956f064d2fc3d77ca2ba351235ecbe180068fa19d91c2eef5fdcfe4cb49f78f674edf8492acba8133086d4bc2ae0ed3447fcd8aa9068a52250a3c40a424e12993c6b7ead850f7b315d28780886b1c3002ea615dd824eb893174728edb64aa4d3d56bec14f997b359ffedef40b403954c934250ad53ca449fd7d4351eea17f9b2c2ce46740d1ba8b92cb0316aafc4ef22dde54781b7bdcc9c2520b7b34f286109a09871da54657742322a460eef7ef635714a7388ce0a974d8006976ef0b809e23428a97ec8fdc75089d8e7290", - "aes-256-cfb1": "d35b46a4c859012482af4b417d2f7643edfa393097030fa010a39fe5047d581f167ad8325c90c1731d36e4e6297ff9f79ce9ea98987921af8d2934cfd47b9eb081996088771889e8a880f4fd80f0ca6c5493e2b1238923f14ed41320ebf8fabadbae88d18e17e0dba0be62e38275a25cbe93bf031c01126c60c23e29e3128c020a80f8dab21dce731430b563bd23ceaadf12b02b10b83c9cee437b1aad38633ec5a7441c8db670ef0ccfeeb69ecc82ce6a67c83358f084c73a4c4750e26e6944a58a9797d100d91fad92b4024d27665593282c7f4059ae28bbea320df1ebb9898c7ce3677e7e67f088adfabe1fd09cf79881ad64dd549bc04f924db5af2d1ef7f6e5b47f1fc3f8c87e7e82577499452ca9daac7e3f012dcd3199f2983eeecd5e504402c1c64f4c8f895c3262ba2831a15a258ed31e7ae92d271ea24a82c1fe064335e540128e3bb21a3ae265d6b729f4949bf24ad90b6fe61704452dd97be091e8fdc22b28c5b2c5451d27e93426e0f147681368579797ccf50c73dc130aff7fd7e4aea5b743a7b06a2a405ea7fb4609522dcde3fa1ca5a46bd2b03c66cf4af5b50ddd3ca47326ce2087ef388220d0fe2889bc72d32fe5f7c3270e429421f5b6c013c9ad137f94dbe1a7526bd54c12e07035af338851e364ef08f9a103142aab8f7f4be6cf2883a899fe018390813ca8465ee30bbdd5508578323b3fe5cf6daf3a5cc9597607018db84cc7ee770f70982de72718a20711dea200027815ec4c1825ea1862fb18b7a55a09002df7fae7668016adb9950fcbff1859973c444cdb3075f1afc65c5636e3137827fdcd91a69c54f04b2a607bf4d6c781463425a5aefdbe8a7c0575b12f43bbda4dec67e597fc87660d702ccd62a809ea8fa5bdf03933f5c7af3da8b3437d592596208439ad752a9a42b5730c8cc29024fdb60cc16a2fad08a0935dc8ee4e4529b74d1021e0942b588497252120cf50d658cad17b3332df97f390ff25deafed5ce07860e8336fa17875975fc609533e7c630310aac1182b052c509729451f4489f992cbd0a8ecb6b7ebc594e806335d3fcf7ddcbec72bffb8dd2b8af7a4f6d4aa0a88b84486a7270eca3ccccc72cce9f6298b8c146879857f3f1baa76b892ee9df89c0d7a865fa2b5dcd1d402feeac7865bca38db1258e7b8fd1583ab3363206e28be79fb3e4d996a9066ec8e0ff9859e15f3e6217542d57bb4922c0b40bdd4e57339dbc99fd6eaf597ba06fbe46e73bec4d3f7f4b164d24472f2a0196f0c9d9ad9ee9ecacda812c815167a348035587d2ef1cf781c814937c9f365a625b534669d36a586096028a144cd564d3163468b3c530cc7d201691dbbe346fdcd1ba3eedf2b133550652913254fc385a277597c5c02b81ed4bdeda4db0ad43e25b01aa03338eabdf83ab9e46b121f96c01e7ccbe50110cfadb9b8f0ab960d01fd71f73f71a883bf16be9eadd8702ade30a7569535f1378bbe4d7098cfb50171818149398580d5b32720304bc1372a0e1f547428922751b2a2ef19c138381607cf9b9487970fa8659ec9454523b7c19c544089e331b21e7b010e9f30e2267d4ccb2867cbeccc962b98f6e4c3f79b30de82fa4d4a1a338282e5184fbd37056c57bd45617fa075aef13db315fd99044baf898fe8371806d587a77e0e4a46d694cdd4e6023862f691993e72f90d1b2fef4e4c76908b82b1dbe499afb158c1f22594df1832927f5924743f0d68a3ebb19cac9b499add0490bfce163094dc78fc8e55e6eb48822bdd119c9ea0a0f0a4fd200cbca966e491f7a7347849e31e82cd8a3f9f0772810bc524d5411565cf428c9f77088e75621be42e1d05f21cff83b72600583930e0b2e9980a5f5550945ea6e1bd47123f6f99d2e9088f00b50c35371072eebfb418dba4f9075716fc5c1d1861069f627b3134e268ee70a8adceb6f402b15c38270c0478afcbaed51e11b4e0b83f7a478960d66337c4cd01834ee531a122aae52cdebb0dcf1bf77115d0a811f8bba743580b83b3aa75b0487117a7af55935a0987591e8ddde96d86dc7c9244bab198e72691c518b5baaec546d2032d3cccf4fd2d585be50934e3a1d8b2a08da9cf21a0cbcda48e0046159f881fcf2d5df7e93465d2214a23063962ee3fd691368adfd938b7a00421fc9ea0129035adfb13dde6562a348de8b3c49d4b8c18516c67bec249de110e32530219c9645ce7e988b6ff02fd43ff0df890193a3a6b65dc08c7e09c39050ba799b11472967c8214817f689b2155755e4785a9b1c5cd8ccd9334f2c75607e6a2747d6dd80edcc8f5b90d70a658e691750d2f9967d9fa20ab70857910c1deebabedb8a8e3f4a6002a97375f05a496961146928a1a28dcdb95f3e8c14632a755232a2cc827749c1b2e1ce6e4d6d5c49ce974275b667962ee770fe24050520b9e318e8a6a6a2ed29a882041e5a17931365e4aa585c5e8da3b7e4b5f9d85698eb4c0fbaded2c46c71b519485a851971b5ea4a4a1df1f846f8ec63a6cd868834fe469d7e6a31ff35bec0abae3f6f51ced5b05ecbe9a950914f661061d95982176ee144aae952f5e9293a37b769d38239e5e812e3a70142bcbcd322680c909dd558ec41d61c967f8efe597faec0074ef7a49331af1ecca9c269790394625c65304390443953b35bafa69e5b0f9318f7b806a1cd88085ada9c81f9be79a0108755e86e299b48b56a611f303ad74d074646e5dff654538767a6f04994497609433277224f46eb02cfaf849f671678d351aebaa20b4d1442b860b539f4b2a802d0c19a7c2b944466d7473c8217397d15e15d3364b67566ab5a1580e1fb6f6d9b54120596cd8aac7c13e8fc1e23cd540abd60c5b27c87d3dde46f3930c8f86b65bad46b661f626a5f9089844c6319a6d255143f479157f1fc81f8304e0337ce73c808f68c8a5e86896b06c759710d1ada5d4575d1f3c94fa5852cf369eb06154331b6f389622e55ba841d80c584ff55ae1b9b5f85ad30af84335d26ee15ebbcc2a66e372d9807582f0395ace5f8e664f343db6d11a97a939cbec73124c81cf61a529075c1b69ec4f6acad7a0d325810b4ac1257e8aa9b97b45fb99a15f2cc6ff2e4ba53811357471ab3a1904505958b9d94462197121a343ecae139ea577a73fb5b0614442934268bd56a64282d9a797d2cbf0d49fb3c538074da2192ca2361a9c2df61076c08c9b63ee24e635ad17727e520c9b4c90a6f0cae312cfae8212e2910cbcbe563feeec3948a89499392f9d05666f579cbd9a0a23e40a3436d92cd603944bc6d37e5ff54ea1a1766bf75231fa9dde362a08fe64d2ceaa26f01a95900aa57d57ea69ff08f85b5b7874282930354d5ecca6077e39d693d123ea94687fc9fb7577f5ccef8e5d609c20dfa366ee366022ff3530c34cfd886e395e8f619b59d374d1dbd97399f88ce832245c09d5d3a5c37f3b4e82efb52a85c1224295b7234233f1ae0f2c84dea5003b769484db1f2f68f8cdf5c6730bda78c21c6d56ae95609e53823e3bc969b445df1ac85e4c64ff3bc59fdc8c3d0038dad4e7a1b83c33eaf62153323ab0830f10b88808357040e7a31dc852adba08478d0454b9c382dee19d880858379bee65fe7c4eee5da1148c8bb511c7c77ccafe3fd502362250047e874ca44901cfbe8977d1704b3d98567ca030357dd45a4eb99bc5f96bba637ee593ea3d95d28b5abcfc958d6a1c4b1b9cac7b5109ce6b2c29ad539c66f43a10b855c62d4ab93d022611b834b4e26e37ebea376da1bd8bc872beb335e57b56b41a234539a7979854a7db0fafe582eecda9f0dda0f5244b345f8721711a103774086674e9e1e897ce26faf7b5f22dd782b27503d81767d372527d80123517e15b57cf3a65b6172e4807f4494b450c32513e562f71fa3b1ebc5c30818825b56e1b3a3e736282d4328aa2799cf6dbcff4b38baf2c86a24854c238d4f18386edbe5339240f0e38b762236e2ee930d0d07219c953ba11023853c048886376a603fb78214845af729ddf56d7198dc3ed87ae9fe836d6d0debb38100a284983ba6b8058a7fba861f7dbb221541b6219424ad20bda2a784b26b0e0b1cc76218be6c0eb16e432f9f5deb4358c4335914e527d5e95b73b29531a298b3a8566064ce817fcd6e14cacdf15298237035afe691f73a72e81c6197447" + "aes-256-cfb1": "d35b46a4c859012482af4b417d2f7643edfa393097030fa010a39fe5047d581f167ad8325c90c1731d36e4e6297ff9f79ce9ea98987921af8d2934cfd47b9eb081996088771889e8a880f4fd80f0ca6c5493e2b1238923f14ed41320ebf8fabadbae88d18e17e0dba0be62e38275a25cbe93bf031c01126c60c23e29e3128c020a80f8dab21dce731430b563bd23ceaadf12b02b10b83c9cee437b1aad38633ec5a7441c8db670ef0ccfeeb69ecc82ce6a67c83358f084c73a4c4750e26e6944a58a9797d100d91fad92b4024d27665593282c7f4059ae28bbea320df1ebb9898c7ce3677e7e67f088adfabe1fd09cf79881ad64dd549bc04f924db5af2d1ef7f6e5b47f1fc3f8c87e7e82577499452ca9daac7e3f012dcd3199f2983eeecd5e504402c1c64f4c8f895c3262ba2831a15a258ed31e7ae92d271ea24a82c1fe064335e540128e3bb21a3ae265d6b729f4949bf24ad90b6fe61704452dd97be091e8fdc22b28c5b2c5451d27e93426e0f147681368579797ccf50c73dc130aff7fd7e4aea5b743a7b06a2a405ea7fb4609522dcde3fa1ca5a46bd2b03c66cf4af5b50ddd3ca47326ce2087ef388220d0fe2889bc72d32fe5f7c3270e429421f5b6c013c9ad137f94dbe1a7526bd54c12e07035af338851e364ef08f9a103142aab8f7f4be6cf2883a899fe018390813ca8465ee30bbdd5508578323b3fe5cf6daf3a5cc9597607018db84cc7ee770f70982de72718a20711dea200027815ec4c1825ea1862fb18b7a55a09002df7fae7668016adb9950fcbff1859973c444cdb3075f1afc65c5636e3137827fdcd91a69c54f04b2a607bf4d6c781463425a5aefdbe8a7c0575b12f43bbda4dec67e597fc87660d702ccd62a809ea8fa5bdf03933f5c7af3da8b3437d592596208439ad752a9a42b5730c8cc29024fdb60cc16a2fad08a0935dc8ee4e4529b74d1021e0942b588497252120cf50d658cad17b3332df97f390ff25deafed5ce07860e8336fa17875975fc609533e7c630310aac1182b052c509729451f4489f992cbd0a8ecb6b7ebc594e806335d3fcf7ddcbec72bffb8dd2b8af7a4f6d4aa0a88b84486a7270eca3ccccc72cce9f6298b8c146879857f3f1baa76b892ee9df89c0d7a865fa2b5dcd1d402feeac7865bca38db1258e7b8fd1583ab3363206e28be79fb3e4d996a9066ec8e0ff9859e15f3e6217542d57bb4922c0b40bdd4e57339dbc99fd6eaf597ba06fbe46e73bec4d3f7f4b164d24472f2a0196f0c9d9ad9ee9ecacda812c815167a348035587d2ef1cf781c814937c9f365a625b534669d36a586096028a144cd564d3163468b3c530cc7d201691dbbe346fdcd1ba3eedf2b133550652913254fc385a277597c5c02b81ed4bdeda4db0ad43e25b01aa03338eabdf83ab9e46b121f96c01e7ccbe50110cfadb9b8f0ab960d01fd71f73f71a883bf16be9eadd8702ade30a7569535f1378bbe4d7098cfb50171818149398580d5b32720304bc1372a0e1f547428922751b2a2ef19c138381607cf9b9487970fa8659ec9454523b7c19c544089e331b21e7b010e9f30e2267d4ccb2867cbeccc962b98f6e4c3f79b30de82fa4d4a1a338282e5184fbd37056c57bd45617fa075aef13db315fd99044baf898fe8371806d587a77e0e4a46d694cdd4e6023862f691993e72f90d1b2fef4e4c76908b82b1dbe499afb158c1f22594df1832927f5924743f0d68a3ebb19cac9b499add0490bfce163094dc78fc8e55e6eb48822bdd119c9ea0a0f0a4fd200cbca966e491f7a7347849e31e82cd8a3f9f0772810bc524d5411565cf428c9f77088e75621be42e1d05f21cff83b72600583930e0b2e9980a5f5550945ea6e1bd47123f6f99d2e9088f00b50c35371072eebfb418dba4f9075716fc5c1d1861069f627b3134e268ee70a8adceb6f402b15c38270c0478afcbaed51e11b4e0b83f7a478960d66337c4cd01834ee531a122aae52cdebb0dcf1bf77115d0a811f8bba743580b83b3aa75b0487117a7af55935a0987591e8ddde96d86dc7c9244bab198e72691c518b5baaec546d2032d3cccf4fd2d585be50934e3a1d8b2a08da9cf21a0cbcda48e0046159f881fcf2d5df7e93465d2214a23063962ee3fd691368adfd938b7a00421fc9ea0129035adfb13dde6562a348de8b3c49d4b8c18516c67bec249de110e32530219c9645ce7e988b6ff02fd43ff0df890193a3a6b65dc08c7e09c39050ba799b11472967c8214817f689b2155755e4785a9b1c5cd8ccd9334f2c75607e6a2747d6dd80edcc8f5b90d70a658e691750d2f9967d9fa20ab70857910c1deebabedb8a8e3f4a6002a97375f05a496961146928a1a28dcdb95f3e8c14632a755232a2cc827749c1b2e1ce6e4d6d5c49ce974275b667962ee770fe24050520b9e318e8a6a6a2ed29a882041e5a17931365e4aa585c5e8da3b7e4b5f9d85698eb4c0fbaded2c46c71b519485a851971b5ea4a4a1df1f846f8ec63a6cd868834fe469d7e6a31ff35bec0abae3f6f51ced5b05ecbe9a950914f661061d95982176ee144aae952f5e9293a37b769d38239e5e812e3a70142bcbcd322680c909dd558ec41d61c967f8efe597faec0074ef7a49331af1ecca9c269790394625c65304390443953b35bafa69e5b0f9318f7b806a1cd88085ada9c81f9be79a0108755e86e299b48b56a611f303ad74d074646e5dff654538767a6f04994497609433277224f46eb02cfaf849f671678d351aebaa20b4d1442b860b539f4b2a802d0c19a7c2b944466d7473c8217397d15e15d3364b67566ab5a1580e1fb6f6d9b54120596cd8aac7c13e8fc1e23cd540abd60c5b27c87d3dde46f3930c8f86b65bad46b661f626a5f9089844c6319a6d255143f479157f1fc81f8304e0337ce73c808f68c8a5e86896b06c759710d1ada5d4575d1f3c94fa5852cf369eb06154331b6f389622e55ba841d80c584ff55ae1b9b5f85ad30af84335d26ee15ebbcc2a66e372d9807582f0395ace5f8e664f343db6d11a97a939cbec73124c81cf61a529075c1b69ec4f6acad7a0d325810b4ac1257e8aa9b97b45fb99a15f2cc6ff2e4ba53811357471ab3a1904505958b9d94462197121a343ecae139ea577a73fb5b0614442934268bd56a64282d9a797d2cbf0d49fb3c538074da2192ca2361a9c2df61076c08c9b63ee24e635ad17727e520c9b4c90a6f0cae312cfae8212e2910cbcbe563feeec3948a89499392f9d05666f579cbd9a0a23e40a3436d92cd603944bc6d37e5ff54ea1a1766bf75231fa9dde362a08fe64d2ceaa26f01a95900aa57d57ea69ff08f85b5b7874282930354d5ecca6077e39d693d123ea94687fc9fb7577f5ccef8e5d609c20dfa366ee366022ff3530c34cfd886e395e8f619b59d374d1dbd97399f88ce832245c09d5d3a5c37f3b4e82efb52a85c1224295b7234233f1ae0f2c84dea5003b769484db1f2f68f8cdf5c6730bda78c21c6d56ae95609e53823e3bc969b445df1ac85e4c64ff3bc59fdc8c3d0038dad4e7a1b83c33eaf62153323ab0830f10b88808357040e7a31dc852adba08478d0454b9c382dee19d880858379bee65fe7c4eee5da1148c8bb511c7c77ccafe3fd502362250047e874ca44901cfbe8977d1704b3d98567ca030357dd45a4eb99bc5f96bba637ee593ea3d95d28b5abcfc958d6a1c4b1b9cac7b5109ce6b2c29ad539c66f43a10b855c62d4ab93d022611b834b4e26e37ebea376da1bd8bc872beb335e57b56b41a234539a7979854a7db0fafe582eecda9f0dda0f5244b345f8721711a103774086674e9e1e897ce26faf7b5f22dd782b27503d81767d372527d80123517e15b57cf3a65b6172e4807f4494b450c32513e562f71fa3b1ebc5c30818825b56e1b3a3e736282d4328aa2799cf6dbcff4b38baf2c86a24854c238d4f18386edbe5339240f0e38b762236e2ee930d0d07219c953ba11023853c048886376a603fb78214845af729ddf56d7198dc3ed87ae9fe836d6d0debb38100a284983ba6b8058a7fba861f7dbb221541b6219424ad20bda2a784b26b0e0b1cc76218be6c0eb16e432f9f5deb4358c4335914e527d5e95b73b29531a298b3a8566064ce817fcd6e14cacdf15298237035afe691f73a72e81c6197447", + "aes-128-ccm": "e574e223994327d0e04130cc96c32a192fdab65b00a1ee2cfeb88a476ff15070bc4d1e4262ac1f8b2b6ad2a52b4dffc7740ca8a6788a99c135cb7a7336f981d6b10c4e0a11d593f9fa66120a2ac47b0a42fa26f9606a63362ac93aa5dd96d6aa96785b378ca4696f36b57c4f9c5bc459fe733e97f5918ad2925df15bdb5de2612b36d1978f23d34f76373f9d27f1354eb38d8e8e4f7e396e63de292bab3388113639f1ece452add95659508b702196c52eeaf3edba4b36b06d55c78146641c5925499693dcc2fe2cb302c5cfe00bdd01656ae176cfc4e65371e9e10690a303516ca4e4bf4ec3fab4085c833817b30d4348b2ac5c5ba9c8ceecdb7c30acb9b73547cd36ff9ad8be1e317d49e16984c7dfcd863f3f65427e70b6aa000a2ae40267ddab8f5c589f047129ae91398eae7a55d7084ec301bb4feb8112ffbe30d6d24a1b95325f46d30da259b35472ca5e2422264e79646acfeaafe79be8d4099648f5c22f5c58fc111ffaaf077659738767605eafdb68e98d2bb76fcf33ceb1f6487644a8770e33118b69dc97209b8fafcb503f444647a6262c499aa9105730c1716a284cafde7280c330f7d4ab0de9bbeb83585fae786e57501f04f3202842567ef724ef6818d40174a4f3ed8f569b9c6802fdeee9cb0dbf5cdd71c76763c939afccca46590ebf56027d5e85f7168698cba6c4e1a0739170ef8090ffc5b7a701b7fd3428a8f23f246936f458d2333ef40f011b2984f1290c353216f0170a809a87eabd767814cbc63c8b5570b7d97d90dce600b7ce93c327449512d5f8c1a170f857c5dd7b2613e368dbb4b85d375c51e2c55dbbd2a49f79b2876766712dbfb8c5937b269659753c8b5996bc5f93e2a0d2f66d022741bea08a6736dcb27624378d5ed070dd0d4a91bb8fb9d548bd87976564239288ef8e2fb18603463f4814523238d5025be1be714115f953af8fe1aab8b65cdb3f902afb937da87851dc232338d2f2cc16cb4fd70f634950f7a6c3420f2d1f565ce65d995d9ecba6f15fd4b94724839f5db57bda2e5260624d8f3b1be424f33c01c03d45282b735d23ebfb7ff295ef7601eb8a79bb025d45ced0ec218a8d1d06f859ff9f971a82ea9a2597f8f2a9d84f4ba73c80408e35621f96105e83639a6fca9a4bcf35e1a4c4a94fe74c197a1625aa92ec191249fb8f2f609e6065acc70825d593d4a6b281bd6c3e80c35afda1528658d50c359319c8a8e39f877348d26e40c8e5384f614fecaa9c31d730553b6d94ccb65d1fb7c771e0ac51ee48ad492f30cc579f729756ebe107a2279c230723145275ca0dde165a77cbb7cd25b48f572e04e5b114c6136c80d5b738281d227dd6adf1fd7aecec2f61e6ae3838cadda81e34de33b5071d5d06f54906acc74eaf544c427b842fa7fc6ee9cd3cf0448ae77e6077f67adbdafcda64b80d6e498ae4f273d32908d0f9803bfc5be3063651f289cf76f80fa98e95c3993fb16493703c294a86490b5d9f707dd1827852d2adea037059bde31dc7273f9e8aa076d15f0aca2a881acf6019232f2356fa36a354b0bfb30a3cfc276d4aeda5f785b0607630779d799b1e6883f3288d2fa2baf5b9594aaaa8eaa44694c8135ff0b2c47fe1f7aac527d6698477ef8a95040fa73c9ce5a853e5703a60ed7d269501d95749555bd945fe5e2bb8e43c20f4b32d5d4b4e02d2abb4afa56b9a9453e87bcbc6f9a1b632994abefddd2a7d6a6713a2a3a65510bb6fa6b8cfc6e79a40e60fbc874dd327dcfea4eca34a92d0a167aada4a119c75a7e027f205a0416197d62651f166df86e477722af6b63b2713bde75663b366cfe7fd216a969a2e88704fa78c68191dc407b746ee27797268bb96a0c6045a0ef6ba7609e6ce4968fa84f663591ac437905c87750df1092d20825803416388f7eb7b47daabbeee0be20be316e923ca30c58d0aaa6dbdd829d963791df140ce243cee0f5ca746aaf380aa1e3ff01e9257284e2862799724f246fb1112cb16e00b7878188f224780b455c4616b71bb14b5f8d94cf7b91ca5de9064547b15351d03e3647e5777e6dec5499e9fa8e3c9fa2af6e495720cb4fddbf6cff3a7790ad5aebe1081011a6514fba67789cc7f84ed5ae31e950a212a311c5e77f83faa30c878ecae1973a50de1d776253c8d1d7d7eb62095121026fca02a518ac2016d931a92cc01d2a46207af336426bb0d1c61a5f287446026347bfc87f9db6f398d02f5383972e651fbc9fc3ba8036351faf5582e15256a1534be863aa6a90d3b9607d070111f538c6602670e64fed025d0c203361dc5433ca6378e3b7794c36247cf9e06a9ece9793db93bbed959a0b1a6559458cb863eaecbb5a1765d1cb2027e8a1a56ef6a908e2398b7a8ea0705fec11dd3f355b14aff3b9c89ee9549ed0bddb017bb351deaf6101a2f74cd530316991f7862689095e413b8962a27979bbd26bd90dbafbbc733ecb7efc2aa08e27ce7117a5fa0ac3db31b85d93e7add40136110b389347cdf81393d536c43072bc2442541e5f52cda8fe3c8a6eaf9802a98ace18b99e9bf0bbe4c358162571468b13391bcc9903462f849487161bff159d51ba99f64a7311e19945bca497bee376a20f8fe9c2153061cfca73716f7ba99e6c4677f70f317baefcb3e81c6550261425b93c67cb42ccaeb0096655b19687de22628325328a71fb5ee7e4eddc986b407562d9572761d437d6b9cadcc5137a9ab751f0a6fb14a28f0f103500855ab573359c9c5eadab54a589e394da3bc6cf6d0518a2227b4c66191ca82da3cb8a5c3b801fefd6995115f1f671f5acdac51e760f87b4a39901b3bfa3082af13f828477ff9a6d8317e91def12c976d2f569cc59681bd76fa31e116b6b9f24c3f3c5c65edf9a37e74079dc3e9c036e8d95c12602559109a91b51b58b203003b431b9f1e02dceb448ef24715857bf08cfc687be90682de75240aa605137a24d198a68ea870f75b774c4057eee4c16f9bf30a13278b19cfbbb6b90173813e50f0221b0859857b4a547040d9a92e828508a57c5407c84597bfbd474c95b96a1d36ddcf86f457d9d141bde7909cae4ea3e8d44f44e4fc620f924d9ab7aff701a29bff7ddb3bd7a91bf7e6dcf16d5cc76863069ef765e009cbeb2476b3a05b7029c24cef98d7755494fd157f8d3ebc141261297401a55ead28070c89636ba6665c6041afb4a6fc3860367cd068e2a6651903b396ee6913528270ca15bc20baba3198dac1f7049c812ea19285daa98914c38edb4cde7a1024a04e218ab550cc36b4da271e8aadd474b539afb3f51240a78f9ec76482ae84f806515a5ff25fdb829e7995a02efbfd60fb23c556904c0a82b93948bf994025b1081b7b2c515644db70e5741700c993a036da6a4b9a3912f04a18f7d63dd5ade693ff3ee9f21098c512d86fba063977471a44532fcb442d41deddd4c4d2f34164759bbba989a86410df53d2471a2ca5cb14f93af266e05f46a54ef6bfcd7794a0efedbd9790cc3ccd677c6c2348d64d5106bca9f9640c87556718853a4d38c3377231d5d9fe51be333542b06bc7b8ca3d98db073462982f746a622305377045c8cbb03a4bfb630cde09505ff3428982cb0c74cd7683db0e98f1f097bbc991f1e98f455ab0d0b8cbe8fff0adc65c9a78251dd3a526006143fe8c1938962d936437a0c52dffe9942a63c6c8dc009f3f5dfbf074c042057c612747cb24ba7c6c459d8c48175de9b218ac46a89b1459dacb4e790a186836e4fa83f13d6c8a5dfed55462d08a176469e579b9b4f7b172accc86a1319762521f0d1a73fc59b211d3361ce97e2c336ec43f481fa8fb95d446bddd714cc6e7c1a68261e29115ef75f30f9b560d377b708dd53f5cbc63b997e88fbdace36d88fdb9147c8b77d041a698a9e3e61e3b8e88a09074feb7855c573c7c97d3bf2fb526778b22a92fd51c8d528ae35f1afafbb3eb7d774dab292b3421b66263261c2e76cef1fc9506b919e6da76fe05339bce7c71eaa67135629a1c963c6442125132382817b73f50b0349687e6445f7afc0b0a4e684c03e14c8263d318e0af03fa6d04384f1bf9ec8fc21477ded9225eaa8a1425d739a4ed2fe5d65a074365efea11c6563369d56f09868b21e74e7842770dd10484091119269df2dd9fcf6b292f86ed4615a85d5473e3615bf268", + "aes-192-ccm": "83886407a39fd6576546f94823168cf8badad628523223df27425c85f442d892610c568a294e5f4958532c1f03104c38c2c02494c483f89bf3fa4ade286ce3ed7f76242e3f53b3e7607e535d23239e2ff71734f836646055c8940d5326c50c3166b78690d22b44d77ee577daf9351e65a55a72482504ef74aaa39a0658cf540878c0c76aa53ac8cde04473ab418950bbd4b680bd98f72a600d59a779d5431599d715d3aa2ff64e5a0e8a355ff79007e8d17768c7d6e4df8e7328432c6e219865be21dbb6963d0cf9c9d8db7ccb26678224cfff639cb767a75215e74878810898b347894acfe2d161b09397a0d0989665b32b3e1d7f9e0714dd8a6ef6dec4fd948305788d187d185f29a78c5c5173ef2258a79335be7fb78beadde8c14a885d14b593ce973a1d8bc12c1cda617c8188e45686828ef107145060aa87e08693953313ca9398f3823374e277de660d1d4a3eeb3ef4a46c901259a41342e473a695c12ad04e1d3ac329c3a4e2342972e415e71dca8e409f439cbd0ddd69ad1c698a823421a89e7735ebfdfd8f64f881a0574e754bc51e87faa8cfa7929d69cafc1fc63fa61e86b345718b4ccd54bf6319b210125c73117459e00ca9e12f2cc75ae6cfc94c23d656eeea64f4cb5f1537865ede7bba117ff30ef0ab723f5f56e1a03df30990489a464db65e094c48a1aeb0b7fe8ac14238a97b1dbd6d38c227b8182fc09a52ea1c99bf0f3e947bf45421e91282ec1d0065a16d84403679479cfaacfef255f34cde8c225c184a1dc55450f6d99069e85f18156fc1bd2895826df392ff4d5b3ec94fdb19868839e1c025418ef851561b86c4e0f424190fdbf889f9535c534edaccaa82beb0001f0f439871134ecc523e92874012cc1aef579cdeb06e8bc7bbea33869c737b90f6992a3e42c1bf45257ee6d617caeded54907d0772604a6e69ce0a72b9dd78fc32aee1082b1264baa44687119c7262f3d8bc0ef7f0aa666c7776f7894ac46eb6454770566d340e69b422af0765a813d40a6711243f1c263e001112034897dae380b3ecff3ad37f90260d5eeb9e94f5575d7b00fc4189b88ab2bcd7c8a14e8435e0169ee35b1f105800f5ea579009fb373a70c92fd64ae7f55f676fcabbb89abd34d0c7ef720256b34054d29b5543aae521fae70297853f42b1253048030259326a59ee75affed53b5cd415c67eca89bf7b98d57cd61689acd8b7847845de5863327b319eb5b2c94fe0ff820f9a83cdce6e853aa984cdcb126df0d08a6a22d36b80531a1b8418125ece7b581dd5511a459364fbe62eb96896549e834f853d14f8c443defc5a4dca3d63e6b77112dc75a69317799d48a06ef8a4b1603ee0d56488080bd68576bff49dcd51cee30714ca6671c10f71c8f0491c59047b1b42962d7080101eaac0da2e451b31d777730bbf0d9b7e16fb5314c7e7e4a23e283d9d74aeef9d6349489b73b1bb2164d2a48a580426b3f793e0fc05bb16057c6aea4751658e9af6e224ac10e24df99ea581c6f460171ff62168f83d8aba8c217cca5be7aa63bc693173a17e816e9594a00f3f4de229adeec50992a46dbb60fa93f795a3590c058ee2b9199cbdef6fef19dd39b1883680c8a90fd267a1f02ed2124e440b0ee9f8d57a20d3788be81ca504c9f10e6191e2114941819bc288363fc3cbc1b78510700442665fb0e5f57e4176c432bb63cd62596a5364f3bdf957eca98ceb15ac3fb1338e8b05122417b8f186008b8c0642e1469164e36ec909b29219b89056009ff82a0d682939b5c7f9ed3cb03e5385c45ec24638c269d8f5a4c8ab8100df3ba84410f373cb237fe6458321e8ceb1c6d3242342e16ec6aafde1ddb6c14782c3ad5d0e70d056ab4d50d396b3030d40e29b096996adc143256205401855d3f6cf76319a8e9fe50c4d1ba99b25cc95f879aca7956625b3aabf794c19040f3d733ee3e13afd0bb335b9ac016e85a4e993b8092b490bc1dae8f3018cf6b04686c3968892ddea53fd5a2d6f6fb40419c860285b35926f3ad8b42d52300e0fb9001cbe03203fb8770084cfd1ce30aa0ac4ceadda45040bf6fc13afcad046f661d68f77125eea6bb7ac791f164f953e11dc8bb56bff7c77417ff1480f88c3de7e4a1f683b5389b09f76323467932737b77337b0e5b174b3f503ec3128af449a467c0474afaf323d3f10a7612b584f936d79eb34f681a2c50f90585fafb39badc9b95fbcbd17abeae938646f335624e9fb55a2a438190f2d1b9a4cb01d6514d750c471c3de46346cf3ed1db90535cef85c5cfc79112c4eb07529481141c025fbddbefb459b1dbe1203ad00a0370a4cdca8cb00e16e1f929883d95b384c2d7a0bc2eadce4faef792edc3f32624d72577d469c59fb58b4dff0017fe9c896c14d5f318054a93d072c49ae996262c86dd1ca26aae216865dab70d4b7d65e229c6c5f9cef32ead78f291d5b91288aaf703a0fa584ea9ed6cadc6af4f7bb68493938dbc533217adf20f68f305500c2135cbb48da2ce23c4b17ca6a97abcc2afc4055fe353c7bb262f0a34eb0ed522dc9117d013116e2e238810c9a8c819d393c0ea0cefa09646d881321ff3a84b733db58a4b850342ad5c904a3cc7107ec0324ae5b45ddcc849838f0a4a4625f6903f4f1630f4aeba2854e47e15e543b0b6d1a986d4bbff6a56305cd277e4f5af5a02656805f69745cf05c83af4b19dd17a277f50f84f002d6ee5f8e3ef72f66adccb7d63dba68625c4332dce69299e7a3049e1bd9b57b6a16a3eb5353ce64814b07e0037ade4ef006110475c0bbc504f68cb2bc3e305fc76f03b30f1e9ef6fa5cf4e332e6aa4e48e0ccac0b53cdd2ab731e4348c5061ef86ab42d5fedb714441692bfc6d4d71e902064d2ad66c69f93308b2f007cb46bacd98d8efa2ec5707856bffc98383a6dfbca790380b29e4b0cff426b45ae83bff46162f2f41a6929a688f9bf54bceedbe507383826be4d1f4c24e1d713005e4ef531b4ba05dc442cf8af23d2cfe6ea3c0e738fa7f4acc30f0dd3321486ebbc040537fa75fea09eb25cc40205a571c7dd9453065a0940e50196c989855080a54c917120de0000c8ed579fe2f62ee60836210b5a301d8ef7ba9b8b02f0a0297d5db03b28c4b1af97a7092262dd6e901747e530fb406c1061b5801b53031eea27ba6834d41a1febf801b10034dbaf198b6c056a1212f72587eb2736906bf57de0744ac986257f23787dce14804aa25f9df41b832c318c0319df7acd0c1af6b86a1762c2173df381586f5773d25ae6b5d94d0eced0364f566bbfef149ae0b86f2b40dca40cfdd168305c991c93ce7e4d02409405283b4a9aa70719a53e6462b8dde54a990851f4921de7bd3d98a0487743db2b06b9ef9531f07de38dc9c18ad66e516d7cefe5a5e1f89cbebb4a2a1d541c3397826f793831bbae018f2c3fe285ce723bc97c242501375168cbd1cb6be285270e40153cd43ef04db8abbae5b506ab85356fc2439916718eb317e4de03502d9f6bed58beecc4fbc9f13ffa8fc6c3066aa554be6d26c42f03a504fee42b205e2886359ae299a95586044a17debddbcfe1a4bcfc9973cf8d12b90577eb825ab3b08f1c254c8fc6e735cebaa012545a6a50ff08745b553103d87c6196977500f59b62bafad78aa27826013cce3c04a897f46450b3af45bb9736c9f09b9106f4cb490d74bfe2718d7608678d404ae8f09a1810ce423650b35aea977659b3aee3355c25caecb2de43da72dd35bd738bdc90118023006616f89a37349648de4e9cdfb9194fdbea84f7d352c540c7b10b7a17c7c1e6e1a70f4ab69b3e035ab3232d45b41e34dfaa10357ad475ff706569217b2d36218746174e377002ef6cbf4dbe629c5459bb62851815206fc0457993e708392ac5644518120797b698cae5388f79b145f639ffb5d146592832018c351ed1111ab109d0960efecca6af6b2db8b6853cef6fc9dae4395be1d48f52bd83c7bb7ebca7a2fa31321d249b255c978a8da149f5f61dd77b4e565221a1a848193eda118e0b77ed8ab30814da6ad33e9ff0ab03af0d2159acfa2bf05e757de865ac38ab8184cd532c3c0afe489bee7b1f3b6ea6f1bf919dd4ae69e60da4462ac89ffd38348d5e20895c80fbd1b2b70f964459a9144c1b1cb1bf1a59dc7736cb0e232acf60609caa0132d6b55e", + "aes-256-ccm": "2d93ad03f4f0c87c08c6731eba622cdb163bbfe8106d56682aa890d7ce86d795fae417bfa8cf9ba9bb29a5d7f74f3f6a4cb0c19bc18d994befb55c96649d5661d84199d80859f5864382f3887bfd59f6e2e14ee13e5e5ddc00ae999bb765da06dd3d893238185d39550f3be47585880f3e16d803af06707aaf6a6a3d1d33fae7c0441b06424227e06836090b40f4d0b78d643ce8039633fea402592c13aa25fc279fe4eaa81c49f62bfc2b69e12ce6eeaf3c5948fe41a7fb230d19ac365f0890506714e0d9595638788291217def97c16daa1562a31fdfd683c03252f204ceed2d91f826031b6b4205fd05c0e8e275aec92fdd978a58b732133a7d84274d206454e76a7f07d7732fcffe2a5a1b9578da898ad552788160de8426ae53db671772be14a1bcf662c4e45b8870db5e99b347ce9e4befc907fb8db0a65fa55920d88f6af79f70810ef67c9ae2ae41f597460c704f956c139631442581fec79b7f6d304eea34cd5c09740175ad682a2434b00de5813329381d485719dd179b3481aa0f96389fb92d04602806136241e54c21a1cfb10ba49bfa5c4200b7e52653fd77d06bcd6884bb3867147d82efd1367121bd5334cb92e5c9e92883e1e009a9757d23df74519e0a89b2255e7c0d81759a8b5604dfc0c73a396edf17b271e76c0b6975a97b36ae4ecc6d84bf3d88eea7c211cb2678527e21bdde0390d357af5739b7bd3040d33a56a00e2784164e44b440d036a6080878c89f3068634f43f0fbaf667279e6a58ccb576ad36a39684299fb0a7079c1741f6f4dbe2ff7509364927b9ac730893762b5bbbd19e0db87c78b1219389b0ee9616ea62dd914ab1013e6f8d2f14b486ae92ccdc7fcc97aefb883af0f7037557a5996261787b87706d6e70252dfeb99a26152aa6b33094a47b2e29e3a35858430ac2ef12f128102d7b1db2ad976a5919be6802a273c5b69531f10084ebcabcd8e1dccd03921502e70c87a36993e6f7267069c30f2283c6540d59a1b6ed5aeeac8bae0d8957704d33bbbfdc06de6a105773907ffbc3390e33f76d6bb41ec2ed2a47e7d3da4ca0e9e0f72676eb230287df656e3479c2a0ab009e69ab0b4bca853bafe740294942bff55ebdc5fbb51b3b4b9c2557a42e2ba5e5d3ce4b8e288035b18b9f24effbc292b47a689c17006c4c4d0d320c4e1264099e19d8e078462c9ff11c7e6a16fb4c35c5ecafe7c2b81e7b40aea4030ad3c0e8fd5b98d50860df02971c3fd71d2e3aaeb13326c8a1470a64d82d77516d82cc34ae03ec3964be369a7f5464d935c8bd961baa679469ff6f3ce124b3b58c018132698235902f4164b87969cce5624f3f05b9f7245db135b9c71e2228555394232da12574fadfe370307821777346df56897cf4c13eeddb3de49199c880096ac5b7f6746f2eba2692f242532e44dc5355baaccf13cc49ba87bcee12c7622afcd5a604542580da29e14c624df3a1788c86dfd3bc901232760d4c0094b4392c2a3936ffa716442a1f20a2bd2e3235541a90c48a31f90346c63847dbd233a626aa9ea6f59812adf0562393e3390cd39872fc87a72377152330e26638361061fed3fbff6a7304a86c5a1a5592f79ab5224e10f7c105b5260c786b3e3824517519e59031d28ff25e1f353790ec3c207f9aae1b89ae1e4d896ba8315e4e2ac2e2e68860e92a6711a18da9e02b24d77e1e4c6e3d8275aefd74048e78a9928d6751efc756b4efb19c35b1a5396bc4711c8b42016471bb64c96ef7cad60000875d92975ba9892fe7cebf67f2b58fe19f7a377f85fed071ef47ea644f6e9bfab3855eec1e736234c4a37849674cfa2b1209d5cb187ff8dbee27dc450f1a1abe7546da3a2150e404080a9771e426b98f880981180f85abff71905f670d12558558f5660a74f9767226349867788488e5f58d5fb5a82aaa660fa97dfd01ccac18aa4a5a81f768ad90aae87f97e64ac95ed910d30fe04a5f02bee4d83d30964ccd75175b90640362bce33c57f0df58ae1eeedf0cb1b1e0ec7805dfc8a58b588e169961398151eba00366913d16148614ea1f4358df7dae78675ff24c1f5ba036789ff4496c0adc38edf43cab5e8f836283994979fd0e04f81fea2c7fadf8734cbc10c3a73873c628491800bbbe4374ac947d808eee1448683534be131cef6d389ec8009437f536b7faaaa4917ae73d587bfd9208aea9bb0f1234ebb6f7b290c22af22173ca601756b8dce74d81363727591091e9eca12e7bdc5d9946d000edffe649c6f5041234d1c2f6bd0b36af16918256c27f60cc5e879c8c460d875707780db0830feb4077d10b0645720f9370427d0e5a9f39723276802318fd6d76ce10cd7a17c28774afc1f84dc3bb245c1f307ab31dba1f661cb1404394bd4de9ba89a507edb14c9d1a5741a2c4cb38177ac49f7c71067000af94db4333eb39a24d37dfb359304cd146caa7d1fce70998293ebcf3f70018043ec4704553fda8278a4c633192ba755f23a0b875a4107d505080f23876ad6ac7fbdf715947b8082cdf7ce8454e901bbae2c3899a1888a697c15a12303def34ee8995cd6aaf805c6edbcc00c657e9c3e0c5bdda96dfcdf9d7d62c39827383cc17f47ae1db308b87f6597a6c7f7910b166596650addbe2b2e33f8bf4e3c7b537f11d8c3895c55345a028b6dde1ba97f606e5914b2f21f26d795faf687c1751259d0506237376f27e0052bc2a81a4135823aeea67168edf6ba6813508eeca74313c0d3f0f0f55f2bdf0366e75e287d8b450f9bf285e642ea04ff07413984c905ecbc9aae2b059c38d1ec00dd0dd1976c8dd91b5baf33f574e17d2ec8849a834a6e77f2c3bbddd896f7aede18d54df6dc53349f7079531748dc4078f1a90abea6046d7e4eff71de9470df5d84b21ce5b69e753deac7e9f6026ae4a49e82858ba2f7c917eb0ac2e0cfa60edd779617619034f3997744c9bc295af2a79a91cfbc59482d8db5a9431e55830ccf9b6bf635bfa2e2fd466529bbe8b9ed22d2ed24c4bced0897152175832aac6ed3247a6b7ab4c47f1bbdf0b71e02d32e06e8986e70db7a01be7f87b689e4cbc59a49f6071f009b3849a6994bac0192c6cba84367403b76ef7e85d5dedf044841895de661ee7673be4433b791d714e2c81f9d70903165b05a4322c7a685105c00fccd6486fb50c4bf7f7ad7fb6cf4cef3bfdb0366b5b4d301c982a660be053a49810b37b3ffd15371bfa9473522aa091bb233bfd57e6d9bba2b829650d1368bb34610ca8de0868673121d55cc67605dd94bdd52fa1ebe37024c9f2d2a4df251af5d9680648a3b41c76c494038f43d228b4c9f657efc7975dd88bdce2a0126c0cb116953801db97ae7ddf4d69435addc3d0c3e60afc23034eb33de4240f6ab4cd8c3a435c1c318655e9313350163c2f8392250be9c42da159e28c443fbec5fb1418b7a4d1a7d6671c94e5a12a6bb60dae4927fc2e701b9d22a1b67c6764c2e5179583697f0f2706b190bc65729a72c1a154bb5c6492b464070932b9feb9baa5d7d3797fdaa6d74d37d75f89a91ab262d1f1aa0d63a83196d4b2fe272067f6a60d629e2b4c93f89363d3a6d537ec21432307fd1b2752ac142cb9b3f1bd4ee2364d369e33a292adcd583206d75eae74d551edb645f0f4296cfa2c7b35666ffa810b797165ea2405f8f5d3da3a0611fec93bb5b36f2ce9fe55e3d6dac2dbbd9e2de22d3270e758b0c7fe22fb717432a845147ecbfe31072c3994a1f4aa2200e1fbe546d599da4eb7fd65b628b81d050ca15c91bb38d3719b578d7af96136366820517226693accc531773a5dba4c1ae0356dfe8fb1a5cb7ac144d2ae6433440ad91ce80145021f145eae1c11bb73ba3c49047e3e3c0bda48602e9a01a520de0e3563c46647b4ded1e9e800a5e65a3eb6a707ed51ce28dc341b52540edab70fc1bd1353a5f2376773dce01b0ac00eec18b3d183afb3b0940e7e144fe85465fac85540d1d5a0ca5dcf298e2aa1c58438723cc367473c01519beb588930640196272b11cfcc8fee8972ab828c2ee8e3f2d40d1ef7e7faaab55d640f0fc033b28ae9d3d70f1e85e8df350b7883ad268f86d8543df4a68349623b4b5ecfb1b2a37708da12548f07526d5ea5834c31afb0ae855395a3f6024977c32897146d38070543bd4cf4085a3fc516f7e021e5ee23ace9a" } }, "aad": "6312bc1a31a878b4b2ef1df84c9b1c42", "authtag": { "aes-128-gcm": "18df427e45e9daf7ac9bc6b80fbc9d91", "aes-192-gcm": "f349e362a080131c428cfd623b6d8eb1", - "aes-256-gcm": "d3a6450ab9b9d2d7cec85556216c3d81" + "aes-256-gcm": "d3a6450ab9b9d2d7cec85556216c3d81", + "aes-128-ccm": "c55887d49c317e18308a3d52c16b939c", + "aes-192-ccm": "4b5fec4ba3c9d98936886787b3dc655e", + "aes-256-ccm": "2cba29297827bbedf8589fc6cf08ff92" } } ] \ No newline at end of file diff --git a/test/index.js b/test/index.js index d1299eb..53faaa3 100644 --- a/test/index.js +++ b/test/index.js @@ -9,13 +9,18 @@ var CIPHERS = Object.keys(modes) var ebtk = require('evp_bytestokey') function isGCM (cipher) { - return modes[cipher].mode === 'GCM' + return modes[cipher].type === 'auth' } function isNode10 () { + if (process.version.slice(0, 3) !== 'v0.') { + return false + } return process.version && process.version.split('.').length === 3 && parseInt(process.version.split('.')[1], 10) <= 10 } - +function isNodev10 () { + return process.version && process.version.split('.').length === 3 && parseInt(process.version.split('.')[0].slice(1), 10) >= 10 +} fixtures.forEach(function (f, i) { CIPHERS.forEach(function (cipher) { if (isGCM(cipher)) return @@ -103,15 +108,32 @@ fixtures.forEach(function (f, i) { CIPHERS.forEach(function (cipher) { if (modes[cipher].mode === 'ECB') return if (isGCM(cipher) && isNode10()) return - + if (modes[cipher].mode === 'CCM' && !isNodev10()) return test('fixture ' + i + ' ' + cipher + '-iv', function (t) { t.plan(isGCM(cipher) ? 4 : 2) - var suite = crypto.createCipheriv(cipher, ebtk(f.password, false, modes[cipher].key).key, isGCM(cipher) ? (Buffer.from(f.iv, 'hex').slice(0, 12)) : (Buffer.from(f.iv, 'hex'))) - var suite2 = _crypto.createCipheriv(cipher, ebtk(f.password, false, modes[cipher].key).key, isGCM(cipher) ? (Buffer.from(f.iv, 'hex').slice(0, 12)) : (Buffer.from(f.iv, 'hex'))) + var suite = crypto.createCipheriv(cipher, ebtk(f.password, false, modes[cipher].key).key, isGCM(cipher) ? (Buffer.from(f.iv, 'hex').slice(0, 12)) : (Buffer.from(f.iv, 'hex')), { + authTagLength: 16 + }) + var suite2 = _crypto.createCipheriv(cipher, ebtk(f.password, false, modes[cipher].key).key, isGCM(cipher) ? (Buffer.from(f.iv, 'hex').slice(0, 12)) : (Buffer.from(f.iv, 'hex')), { + authTagLength: 16 + }) var buf = Buffer.alloc(0) var buf2 = Buffer.alloc(0) - + if (isGCM(cipher)) { + if (modes[cipher].mode === 'CCM') { + var plainLen = Buffer.from(f.text).length + suite.setAAD(Buffer.from(f.aad, 'hex'), { + plaintextLength: plainLen + }) + suite2.setAAD(Buffer.from(f.aad, 'hex'), { + plaintextLength: plainLen + }) + } else { + suite.setAAD(Buffer.from(f.aad, 'hex')) + suite2.setAAD(Buffer.from(f.aad, 'hex')) + } + } suite.on('data', function (d) { buf = Buffer.concat([buf, d]) }) @@ -137,11 +159,6 @@ fixtures.forEach(function (f, i) { } }) - if (isGCM(cipher)) { - suite.setAAD(Buffer.from(f.aad, 'hex')) - suite2.setAAD(Buffer.from(f.aad, 'hex')) - } - suite2.write(Buffer.from(f.text)) suite2.end() suite.write(Buffer.from(f.text)) @@ -149,17 +166,35 @@ fixtures.forEach(function (f, i) { }) test('fixture ' + i + ' ' + cipher + '-legacy-iv', function (t) { + if (modes[cipher].mode === 'CCM') { + t.end() + return + } t.plan(isGCM(cipher) ? 6 : 4) - var suite = crypto.createCipheriv(cipher, ebtk(f.password, false, modes[cipher].key).key, isGCM(cipher) ? (Buffer.from(f.iv, 'hex').slice(0, 12)) : (Buffer.from(f.iv, 'hex'))) - var suite2 = _crypto.createCipheriv(cipher, ebtk(f.password, false, modes[cipher].key).key, isGCM(cipher) ? (Buffer.from(f.iv, 'hex').slice(0, 12)) : (Buffer.from(f.iv, 'hex'))) + var suite = crypto.createCipheriv(cipher, ebtk(f.password, false, modes[cipher].key).key, isGCM(cipher) ? (Buffer.from(f.iv, 'hex').slice(0, 12)) : (Buffer.from(f.iv, 'hex')), { + authTagLength: 16 + }) + var suite2 = _crypto.createCipheriv(cipher, ebtk(f.password, false, modes[cipher].key).key, isGCM(cipher) ? (Buffer.from(f.iv, 'hex').slice(0, 12)) : (Buffer.from(f.iv, 'hex')), { + authTagLength: 16 + }) var buf = Buffer.alloc(0) var buf2 = Buffer.alloc(0) var inbuf = Buffer.from(f.text) var mid = ~~(inbuf.length / 2) if (isGCM(cipher)) { - suite.setAAD(Buffer.from(f.aad, 'hex')) - suite2.setAAD(Buffer.from(f.aad, 'hex')) + if (modes[cipher].mode === 'CCM') { + var plainLen = Buffer.from(f.text).length + suite.setAAD(Buffer.from(f.aad, 'hex'), { + plaintextLength: plainLen + }) + suite2.setAAD(Buffer.from(f.aad, 'hex'), { + plaintextLength: plainLen + }) + } else { + suite.setAAD(Buffer.from(f.aad, 'hex')) + suite2.setAAD(Buffer.from(f.aad, 'hex')) + } } buf = Buffer.concat([buf, suite.update(inbuf.slice(0, mid))]) @@ -181,9 +216,13 @@ fixtures.forEach(function (f, i) { test('fixture ' + i + ' ' + cipher + '-iv-decrypt', function (t) { t.plan(2) - var suite = crypto.createDecipheriv(cipher, ebtk(f.password, false, modes[cipher].key).key, isGCM(cipher) ? (Buffer.from(f.iv, 'hex').slice(0, 12)) : (Buffer.from(f.iv, 'hex'))) + var suite = crypto.createDecipheriv(cipher, ebtk(f.password, false, modes[cipher].key).key, isGCM(cipher) ? (Buffer.from(f.iv, 'hex').slice(0, 12)) : (Buffer.from(f.iv, 'hex')), { + authTagLength: 16 + }) var buf = Buffer.alloc(0) - var suite2 = _crypto.createDecipheriv(cipher, ebtk(f.password, false, modes[cipher].key).key, isGCM(cipher) ? (Buffer.from(f.iv, 'hex').slice(0, 12)) : (Buffer.from(f.iv, 'hex'))) + var suite2 = _crypto.createDecipheriv(cipher, ebtk(f.password, false, modes[cipher].key).key, isGCM(cipher) ? (Buffer.from(f.iv, 'hex').slice(0, 12)) : (Buffer.from(f.iv, 'hex')), { + authTagLength: 16 + }) var buf2 = Buffer.alloc(0) suite.on('data', function (d) { @@ -208,10 +247,26 @@ fixtures.forEach(function (f, i) { }) if (isGCM(cipher)) { - suite.setAuthTag(Buffer.from(f.authtag[cipher], 'hex')) - suite2.setAuthTag(Buffer.from(f.authtag[cipher], 'hex')) - suite.setAAD(Buffer.from(f.aad, 'hex')) - suite2.setAAD(Buffer.from(f.aad, 'hex')) + if (modes[cipher].mode === 'CCM') { + var plainLen = Buffer.from(f.text).length + suite.setAuthTag(Buffer.from(f.authtag[cipher], 'hex'), { + plaintextLength: plainLen + }) + suite2.setAuthTag(Buffer.from(f.authtag[cipher], 'hex'), { + plaintextLength: plainLen + }) + suite.setAAD(Buffer.from(f.aad, 'hex'), { + plaintextLength: plainLen + }) + suite2.setAAD(Buffer.from(f.aad, 'hex'), { + plaintextLength: plainLen + }) + } else { + suite.setAuthTag(Buffer.from(f.authtag[cipher], 'hex')) + suite2.setAuthTag(Buffer.from(f.authtag[cipher], 'hex')) + suite.setAAD(Buffer.from(f.aad, 'hex')) + suite2.setAAD(Buffer.from(f.aad, 'hex')) + } } suite2.write(Buffer.from(f.results.cipherivs[cipher], 'hex')) @@ -220,6 +275,10 @@ fixtures.forEach(function (f, i) { suite.end() }) test('fixture ' + i + ' ' + cipher + '-decrypt-legacy', function (t) { + if (modes[cipher].mode === 'CCM') { + t.end() + return + } t.plan(4) var suite = crypto.createDecipheriv(cipher, ebtk(f.password, false, modes[cipher].key).key, isGCM(cipher) ? (Buffer.from(f.iv, 'hex').slice(0, 12)) : (Buffer.from(f.iv, 'hex'))) var buf = Buffer.alloc(0) @@ -432,12 +491,45 @@ test('correctly handle incremental base64 output', function (t) { }) var gcmTest = [ + { + key: '68d010dad5295e1f4f485f35cff46c35d423797bf4cd536d4943d787e00f6f07', + length: 7, + answer: '8fc8085a', + tag: 'fb920e420324e21a56ad76336efe7c97', + ivFill: 7, + authTagLength: 4, + ccmAnswer: 'f0ed92f3', + ccmTag: '83c05cd2' + }, { key: '68d010dad5295e1f4f485f35cff46c35d423797bf4cd536d4943d787e00f6f07', length: 8, answer: '44d0f292', tag: '1f21c63664fc5262827b9624dee894bd', - ivFill: 9 + ivFill: 9, + authTagLength: 6, + ccmAnswer: '066550ba', + ccmTag: 'd52d16412aa4' + }, + { + key: '68d010dad5295e1f4f485f35cff46c35d423797bf4cd536d4943d787e00f6f07', + length: 10, + answer: 'b3cc0140', + tag: '6dd36794682d6039265cdda8a12bb86e', + ivFill: 3, + authTagLength: 8, + ccmAnswer: 'b21934c1', + ccmTag: 'd52ab76f95be5caa' + }, + { + key: '68d010dad5295e1f4f485f35cff46c35d423797bf4cd536d4943d787e00f6f07', + length: 13, + answer: '4c7d98be', + tag: 'bdfe042f9c039752a9bbd9c864b9c6ec', + ivFill: 4, + authTagLength: 10, + ccmAnswer: '2e85269c', + ccmTag: 'b089b345b5f8804b7506' }, { key: '9ba693ec61afc9b7950f9177780b3533126af40a7596c662e26e6d6bbf536030', @@ -461,8 +553,8 @@ var gcmTest = [ tag: '9a0d845168a1491e17217a20a75defb0' } ] -function testIV (t, length, answer, tag, key, ivFill) { - t.test('key length ' + length, function (t) { +function testIV (t, length, answer, tag, key, ivFill, authTagLength, ccmAnswer, ccmTag) { + t.test('gcm key length ' + length, function (t) { t.plan(3) var iv = Buffer.alloc(length, ivFill) var cipher = crypto.createCipheriv('aes-256-gcm', key, iv) @@ -475,10 +567,33 @@ function testIV (t, length, answer, tag, key, ivFill) { var decrypted = decipher.update(Buffer.from(answer, 'hex')) t.equals(decrypted.toString(), 'fooo') }) + if (length < 14) { + t.test('ccm key length ' + length, function (t) { + t.plan(4) + var iv = Buffer.alloc(length, ivFill) + var cipher = crypto.createCipheriv('aes-256-ccm', key, iv, { + authTagLength: authTagLength + }) + var out = cipher.update('fooo').toString('hex') + t.equals(out, ccmAnswer) + cipher.final() + var ourAuth = cipher.getAuthTag() + t.equals(ccmTag, ourAuth.toString('hex')) + var decipher = crypto.createDecipheriv('aes-256-ccm', key, iv, { + authTagLength: authTagLength + }) + decipher.setAuthTag(ourAuth) + var decrypted = decipher.update(Buffer.from(out, 'hex')) + t.doesNotThrow(function () { + decipher.final() + }) + t.equals(decrypted.toString(), 'fooo') + }) + } } test('different IV lengths work for GCM', function (t) { gcmTest.forEach(function (item) { - testIV(t, item.length, item.answer, item.tag, Buffer.from(item.key, 'hex'), item.ivFill) + testIV(t, item.length, item.answer, item.tag, Buffer.from(item.key, 'hex'), item.ivFill, item.authTagLength, item.ccmAnswer, item.ccmTag) }) }) test('handle long uft8 plaintexts', function (t) {