forked from D0n9X1n/hexo-blog-encrypt
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
155 lines (129 loc) · 4.59 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/* global hexo, __dirname */
'use strict';
const crypto = require('crypto');
const fs = require('hexo-fs');
const log = require('hexo-log')({ 'debug': false, 'slient': false });
const path = require('path');
const defaultConfig = {
'abstract': 'Here\'s something encrypted, password is required to continue reading.',
'message': 'Hey, password is required here.',
'template': fs.readFileSync(path.resolve(__dirname, './lib/template.html')).toString(),
'wrong_pass_message': 'Oh, this is an invalid password. Check and try again, please.',
'wrong_hash_message': 'OOPS, these decrypted content may changed, but you can still have a look.',
};
const keySalt = textToArray('hexo-blog-encrypt的作者们都是大帅比!');
const ivSalt = textToArray('hexo-blog-encrypt是地表最强Hexo加密插件!');
hexo.extend.filter.register('after_post_render', (data) => {
const tagEncryptPairs = [];
let password = data.password;
let tagUsed = false;
if (hexo.config.encrypt === undefined) {
hexo.config.encrypt = [];
}
if(('encrypt' in hexo.config) && ('tags' in hexo.config.encrypt)){
hexo.config.encrypt.tags.forEach((tagObj) => {
tagEncryptPairs[tagObj.name] = tagObj.password;
});
}
if (data.tags) {
data.tags.forEach((cTag) => {
if (tagEncryptPairs.hasOwnProperty(cTag.name)) {
tagUsed = password ? tagUsed : cTag.name;
password = password || tagEncryptPairs[cTag.name];
}
});
}
if(password == undefined){
return data;
}
password = password.toString();
// make sure toc can work.
data.origin = data.content;
// ------------
// Remove in v3.1.0
const deprecatedConfigs = [
'default_template',
'default_abstract',
'default_message',
'default_decryption_error',
'default_no_content_error',
];
const configKeys = [
'template',
'abstract',
'message',
'wrong_pass_message',
'wrong_hash_message',
];
deprecatedConfigs.forEach((key, index) => {
if(key in hexo.config.encrypt) {
log.warn(`hexo-blog-encrypt: "${key}" is DEPRECATED, please change to newer API: "${configKeys[index]}"`);
hexo.config.encrypt[configKeys[index]] = hexo.config.encrypt[key];
}
});
// ------------
// Let's rock n roll
const config = Object.assign(defaultConfig, hexo.config.encrypt, data);
if (tagUsed === false) {
log.info(`hexo-blog-encrypt: encrypting "${data.title.trim()}" based on the password configured in Front-matter.`);
} else {
log.info(`hexo-blog-encrypt: encrypting "${data.title.trim()}" based on Tag: "${tagUsed}".`);
}
data.content = data.content.trim();
data.encrypt = true;
const key = crypto.pbkdf2Sync(password, keySalt, 1024, 32, 'sha256');
const iv = crypto.pbkdf2Sync(password, ivSalt, 512, 16, 'sha256');
const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
const hmac = crypto.createHmac('sha256', key);
let encryptedData = cipher.update(data.content, 'utf8', 'hex');
hmac.update(data.content, 'utf8');
encryptedData += cipher.final('hex');
const hmacDigest = hmac.digest('hex');
data.content = config.template.replace(/{{hbeEncryptedData}}/g, encryptedData)
.replace(/{{hbeHmacDigest}}/g, hmacDigest)
.replace(/{{hbeWrongPassMessage}}/g, config.wrong_pass_message)
.replace(/{{hbeWrongHashMessage}}/g, config.wrong_hash_message)
.replace(/{{hbeMessage}}/g, config.message);
data.content += `<script src="${hexo.config.root}lib/blog-encrypt.js"></script><link href="${hexo.config.root}css/blog-encrypt.css" rel="stylesheet" type="text/css">`;
data.excerpt = data.more = config.abstract;
return data;
}, 1000);
hexo.extend.generator.register('hexo-blog-encrypt', () => [
{
'data': () => fs.createReadStream(path.resolve(__dirname, './lib/blog-encrypt.css')),
'path': 'css/blog-encrypt.css',
},
{
'data': () => fs.createReadStream(path.resolve(__dirname, './lib/blog-encrypt.js')),
'path': 'lib/blog-encrypt.js',
},
]);
// Utils functions
function textToArray(s) {
var i = s.length;
var n = 0;
var ba = new Array()
for (var j = 0; j < i;) {
var c = s.codePointAt(j);
if (c < 128) {
ba[n++] = c;
j++;
} else if ((c > 127) && (c < 2048)) {
ba[n++] = (c >> 6) | 192;
ba[n++] = (c & 63) | 128;
j++;
} else if ((c > 2047) && (c < 65536)) {
ba[n++] = (c >> 12) | 224;
ba[n++] = ((c >> 6) & 63) | 128;
ba[n++] = (c & 63) | 128;
j++;
} else {
ba[n++] = (c >> 18) | 240;
ba[n++] = ((c >> 12) & 63) | 128;
ba[n++] = ((c >> 6) & 63) | 128;
ba[n++] = (c & 63) | 128;
j += 2;
}
}
return new Uint8Array(ba);
}