Add keypair to local account
This commit is contained in:
		
							parent
							
								
									7b0f93464a
								
							
						
					
					
						commit
						001d5faac9
					
				
					 10 changed files with 146 additions and 0 deletions
				
			
		
							
								
								
									
										1
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							|  | @ -1,6 +1,7 @@ | ||||||
| /.config | /.config | ||||||
| /.vscode | /.vscode | ||||||
| /node_modules | /node_modules | ||||||
|  | /build | ||||||
| /built | /built | ||||||
| /data | /data | ||||||
| npm-debug.log | npm-debug.log | ||||||
|  |  | ||||||
							
								
								
									
										9
									
								
								binding.gyp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								binding.gyp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | ||||||
|  | { | ||||||
|  | 	'targets': [ | ||||||
|  | 		{ | ||||||
|  | 			'target_name': 'crypto_key', | ||||||
|  | 			'sources': ['src/crypto_key.cc'], | ||||||
|  | 			'include_dirs': ['<!(node -e "require(\'nan\')")'] | ||||||
|  | 		} | ||||||
|  | 	] | ||||||
|  | } | ||||||
|  | @ -69,6 +69,7 @@ gulp.task('build:ts', () => { | ||||||
| 
 | 
 | ||||||
| gulp.task('build:copy', () => | gulp.task('build:copy', () => | ||||||
| 	gulp.src([ | 	gulp.src([ | ||||||
|  | 		'./build/Release/crypto_key.node', | ||||||
| 		'./src/**/assets/**/*', | 		'./src/**/assets/**/*', | ||||||
| 		'!./src/web/app/**/assets/**/*' | 		'!./src/web/app/**/assets/**/*' | ||||||
| 	]).pipe(gulp.dest('./built/')) | 	]).pipe(gulp.dest('./built/')) | ||||||
|  |  | ||||||
|  | @ -145,6 +145,7 @@ | ||||||
| 		"morgan": "1.9.0", | 		"morgan": "1.9.0", | ||||||
| 		"ms": "2.1.1", | 		"ms": "2.1.1", | ||||||
| 		"multer": "1.3.0", | 		"multer": "1.3.0", | ||||||
|  | 		"nan": "^2.10.0", | ||||||
| 		"node-sass": "4.7.2", | 		"node-sass": "4.7.2", | ||||||
| 		"node-sass-json-importer": "3.1.5", | 		"node-sass-json-importer": "3.1.5", | ||||||
| 		"nprogress": "0.2.0", | 		"nprogress": "0.2.0", | ||||||
|  |  | ||||||
|  | @ -59,6 +59,7 @@ export type IUser = { | ||||||
| 	is_suspended: boolean; | 	is_suspended: boolean; | ||||||
| 	keywords: string[]; | 	keywords: string[]; | ||||||
| 	account: { | 	account: { | ||||||
|  | 		keypair: string; | ||||||
| 		email: string; | 		email: string; | ||||||
| 		links: string[]; | 		links: string[]; | ||||||
| 		password: string; | 		password: string; | ||||||
|  | @ -160,6 +161,7 @@ export const pack = ( | ||||||
| 	delete _user.latest_post; | 	delete _user.latest_post; | ||||||
| 
 | 
 | ||||||
| 	// Remove private properties
 | 	// Remove private properties
 | ||||||
|  | 	delete _user.account.keypair; | ||||||
| 	delete _user.account.password; | 	delete _user.account.password; | ||||||
| 	delete _user.account.token; | 	delete _user.account.token; | ||||||
| 	delete _user.account.two_factor_temp_secret; | 	delete _user.account.two_factor_temp_secret; | ||||||
|  |  | ||||||
|  | @ -1,6 +1,7 @@ | ||||||
| import * as uuid from 'uuid'; | import * as uuid from 'uuid'; | ||||||
| import * as express from 'express'; | import * as express from 'express'; | ||||||
| import * as bcrypt from 'bcryptjs'; | import * as bcrypt from 'bcryptjs'; | ||||||
|  | import { generate as generateKeypair } from '../../crypto_key'; | ||||||
| import recaptcha = require('recaptcha-promise'); | import recaptcha = require('recaptcha-promise'); | ||||||
| import User, { IUser, validateUsername, validatePassword, pack } from '../models/user'; | import User, { IUser, validateUsername, validatePassword, pack } from '../models/user'; | ||||||
| import generateUserToken from '../common/generate-native-user-token'; | import generateUserToken from '../common/generate-native-user-token'; | ||||||
|  | @ -119,6 +120,7 @@ export default async (req: express.Request, res: express.Response) => { | ||||||
| 		username: username, | 		username: username, | ||||||
| 		username_lower: username.toLowerCase(), | 		username_lower: username.toLowerCase(), | ||||||
| 		account: { | 		account: { | ||||||
|  | 			keypair: generateKeypair(), | ||||||
| 			token: secret, | 			token: secret, | ||||||
| 			email: null, | 			email: null, | ||||||
| 			links: null, | 			links: null, | ||||||
|  |  | ||||||
							
								
								
									
										111
									
								
								src/crypto_key.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								src/crypto_key.cc
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,111 @@ | ||||||
|  | #include <nan.h> | ||||||
|  | #include <openssl/bio.h> | ||||||
|  | #include <openssl/buffer.h> | ||||||
|  | #include <openssl/crypto.h> | ||||||
|  | #include <openssl/pem.h> | ||||||
|  | #include <openssl/rsa.h> | ||||||
|  | #include <openssl/x509.h> | ||||||
|  | 
 | ||||||
|  | NAN_METHOD(extractPublic) | ||||||
|  | { | ||||||
|  | 	const auto sourceString = info[0]->ToString(); | ||||||
|  | 	if (!sourceString->IsOneByte()) { | ||||||
|  | 		Nan::ThrowError("Malformed character found"); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	size_t sourceLength = sourceString->Length(); | ||||||
|  | 	const auto sourceBuf = new char[sourceLength]; | ||||||
|  | 
 | ||||||
|  | 	Nan::DecodeWrite(sourceBuf, sourceLength, sourceString); | ||||||
|  | 
 | ||||||
|  | 	const auto source = BIO_new_mem_buf(sourceBuf, sourceLength); | ||||||
|  | 	if (source == nullptr) { | ||||||
|  | 		Nan::ThrowError("Memory allocation failed"); | ||||||
|  | 		delete sourceBuf; | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	const auto rsa = PEM_read_bio_RSAPrivateKey(source, nullptr, nullptr, nullptr); | ||||||
|  | 
 | ||||||
|  | 	BIO_free(source); | ||||||
|  | 	delete sourceBuf; | ||||||
|  | 
 | ||||||
|  | 	if (rsa == nullptr) { | ||||||
|  | 		Nan::ThrowError("Decode failed"); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	const auto destination = BIO_new(BIO_s_mem()); | ||||||
|  | 	if (destination == nullptr) { | ||||||
|  | 		Nan::ThrowError("Memory allocation failed"); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	const auto result = PEM_write_bio_RSAPublicKey(destination, rsa); | ||||||
|  | 
 | ||||||
|  | 	RSA_free(rsa); | ||||||
|  | 
 | ||||||
|  | 	if (result != 1) { | ||||||
|  | 		Nan::ThrowError("Public key extraction failed"); | ||||||
|  | 		BIO_free(destination); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	char *pem; | ||||||
|  | 	const auto pemLength = BIO_get_mem_data(destination, &pem); | ||||||
|  | 
 | ||||||
|  | 	info.GetReturnValue().Set(Nan::Encode(pem, pemLength)); | ||||||
|  | 	BIO_free(destination); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | NAN_METHOD(generate) | ||||||
|  | { | ||||||
|  | 	const auto exponent = BN_new(); | ||||||
|  | 	const auto mem = BIO_new(BIO_s_mem()); | ||||||
|  | 	const auto rsa = RSA_new(); | ||||||
|  | 	char *data; | ||||||
|  | 	long result; | ||||||
|  | 
 | ||||||
|  | 	if (exponent == nullptr || mem == nullptr || rsa == nullptr) { | ||||||
|  | 		Nan::ThrowError("Memory allocation failed"); | ||||||
|  | 		goto done; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	result = BN_set_word(exponent, 65537); | ||||||
|  | 	if (result != 1) { | ||||||
|  | 		Nan::ThrowError("Exponent setting failed"); | ||||||
|  | 		goto done; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	result = RSA_generate_key_ex(rsa, 2048, exponent, nullptr); | ||||||
|  | 	if (result != 1) { | ||||||
|  | 		Nan::ThrowError("Key generation failed"); | ||||||
|  | 		goto done; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	result = PEM_write_bio_RSAPrivateKey(mem, rsa, NULL, NULL, 0, NULL, NULL); | ||||||
|  | 	if (result != 1) { | ||||||
|  | 		Nan::ThrowError("Key export failed"); | ||||||
|  | 		goto done; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	result = BIO_get_mem_data(mem, &data); | ||||||
|  | 	info.GetReturnValue().Set(Nan::Encode(data, result)); | ||||||
|  | 
 | ||||||
|  | done: | ||||||
|  | 	RSA_free(rsa); | ||||||
|  | 	BIO_free(mem); | ||||||
|  | 	BN_free(exponent); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | NAN_MODULE_INIT(InitAll) | ||||||
|  | { | ||||||
|  | 	Nan::Set(target, Nan::New<v8::String>("extractPublic").ToLocalChecked(), | ||||||
|  | 		Nan::GetFunction(Nan::New<v8::FunctionTemplate>(extractPublic)).ToLocalChecked()); | ||||||
|  | 
 | ||||||
|  | 	Nan::Set(target, Nan::New<v8::String>("generate").ToLocalChecked(), | ||||||
|  | 		Nan::GetFunction(Nan::New<v8::FunctionTemplate>(generate)).ToLocalChecked()); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | NODE_MODULE(crypto_key, InitAll); | ||||||
							
								
								
									
										1
									
								
								src/crypto_key.d.ts
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/crypto_key.d.ts
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1 @@ | ||||||
|  | export function generate(): String; | ||||||
|  | @ -1161,6 +1161,7 @@ function insertSakurako(opts) { | ||||||
| 		username: 'sakurako', | 		username: 'sakurako', | ||||||
| 		username_lower: 'sakurako', | 		username_lower: 'sakurako', | ||||||
| 		account: { | 		account: { | ||||||
|  | 			keypair: '-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAtdTG9rlFWjNqhgbg2V6X5XF1WpQXZS3KNXykEWl2UAiMyfVV\nBvf3zQP0dDEdNtcqdPJgis03bpiHCzQusc/YLyHYB0m+TJXsxJatb8cqUogOFeE4\ngQ4Dc5kAT6gLh/d4yz03EIg9bizX07EiGWnZqWxb+21ypqsPxST64sAtG9f5O/G4\nXe2m3cSbfAAvEUP1Ig1LUNyJB4jhM60w1cQic/qO8++sk/+GoX9g71X+i4NArGv+\n1c11acDIIPGAAQpFeYVeGaKakNDNp8RtJJp8R8FLwJXZ4/gATBnScCiHUSrGfRly\nYyR0w/BNlQ6/NijAdB9pR5csPvyIPkx1gauZewIDAQABAoIBAQCwWf/mhuY2h6uG\n9eDZsZ7Mj2/sO7k9Dl4R5iMSKCDxmnlB3slqitExa+aJUqEs8R5icjkkJcjfYNuJ\nCEFJf3YCsGZfGyyQBtCuEh2ATcBEb2SJ3/f3YuoCEaB1oVwdsOzc4TAovpol4yQo\nUqHp1/mdElVb01jhQQN4h1c02IJnfzvfU1C8szBni+Etfd+MxqGfv006DY3KOEb3\nlCrCS3GmooJW2Fjj7q1kCcaEQbMB1/aQHLXd1qe3KJOzXh3Voxsp/jEH0hvp2TII\nfY9UK+b7mA+xlvXwKuTkHVaZm0ylg0nbembS8MF4GfFMujinSexvLrVKaQhdMFoF\nvBLxHYHRAoGBANfNVYJYeCDPFNLmak5Xg33Rfvc2II8UmrZOVdhOWs8ZK0pis9e+\nPo2MKtTzrzipXI2QXv5w7kO+LJWNDva+xRlW8Wlj9Dde9QdQ7Y8+dk7SJgf24DzM\n023elgX5DvTeLODjStk6SMPRL0FmGovUqAAA8ZeHtJzkIr1HROWnQiwnAoGBANez\nhFwKnVoQu0RpBz/i4W0RKIxOwltN2zmlN8KjJPhSy00A7nBUfKLRbcwiSHE98Yi/\nUrXwMwR5QeD2ngngRppddJnpiRfjNjnsaqeqNtpO8AxB3XjpCC5zmHUMFHKvPpDj\n1zU/F44li0YjKcMBebZy9PbfAjrIgJfxhPo/oXiNAoGAfx6gaTjOAp2ZaaZ7Jozc\nkyft/5et1DrR6+P3I4T8bxQncRj1UXfqhxzzOiAVrm3tbCKIIp/JarRCtRGzp9u2\nZPfXGzra6CcSdW3Rkli7/jBCYNynOIl7XjQI8ZnFmq6phwu80ntH07mMeZy4tHff\nQqlLpvQ0i1rDr/Wkexdsnm8CgYBgxha9ILoF/Xm3MJPjEsxmnYsen/tM8XpIu5pv\nxbhBfQvfKWrQlOcyOVnUexEbVVo3KvdVz0VkXW60GpE/BxNGEGXO49rxD6x1gl87\nh/+CJGZIaYiOxaY5CP2+jcPizEL6yG32Yq8TxD5fIkmLRu8vbxX+aIFclDY1dVNe\n3wt3xQKBgGEL0EjwRch+P2V+YHAhbETPrEqJjHRWT95pIdF9XtC8fasSOVH81cLX\nXXsX1FTvOJNwG9Nk8rQjYJXGTb2O/2unaazlYUwxKwVpwuGzz/vhH/roHZBAkIVT\njvpykpn9QMezEdpzj5BEv01QzSYBPzIh5myrpoJIoSW7py7zFG3h\n-----END RSA PRIVATE KEY-----\n', | ||||||
| 			token: '!00000000000000000000000000000000', | 			token: '!00000000000000000000000000000000', | ||||||
| 			password: '$2a$08$FnHXg3tP.M/kINWgQSXNqeoBsiVrkj.ecXX8mW9rfBzMRkibYfjYy', // HimawariDaisuki06160907
 | 			password: '$2a$08$FnHXg3tP.M/kINWgQSXNqeoBsiVrkj.ecXX8mW9rfBzMRkibYfjYy', // HimawariDaisuki06160907
 | ||||||
| 			profile: {}, | 			profile: {}, | ||||||
|  | @ -1175,6 +1176,7 @@ function insertHimawari(opts) { | ||||||
| 		username: 'himawari', | 		username: 'himawari', | ||||||
| 		username_lower: 'himawari', | 		username_lower: 'himawari', | ||||||
| 		account: { | 		account: { | ||||||
|  | 			keypair: '-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAtdTG9rlFWjNqhgbg2V6X5XF1WpQXZS3KNXykEWl2UAiMyfVV\nBvf3zQP0dDEdNtcqdPJgis03bpiHCzQusc/YLyHYB0m+TJXsxJatb8cqUogOFeE4\ngQ4Dc5kAT6gLh/d4yz03EIg9bizX07EiGWnZqWxb+21ypqsPxST64sAtG9f5O/G4\nXe2m3cSbfAAvEUP1Ig1LUNyJB4jhM60w1cQic/qO8++sk/+GoX9g71X+i4NArGv+\n1c11acDIIPGAAQpFeYVeGaKakNDNp8RtJJp8R8FLwJXZ4/gATBnScCiHUSrGfRly\nYyR0w/BNlQ6/NijAdB9pR5csPvyIPkx1gauZewIDAQABAoIBAQCwWf/mhuY2h6uG\n9eDZsZ7Mj2/sO7k9Dl4R5iMSKCDxmnlB3slqitExa+aJUqEs8R5icjkkJcjfYNuJ\nCEFJf3YCsGZfGyyQBtCuEh2ATcBEb2SJ3/f3YuoCEaB1oVwdsOzc4TAovpol4yQo\nUqHp1/mdElVb01jhQQN4h1c02IJnfzvfU1C8szBni+Etfd+MxqGfv006DY3KOEb3\nlCrCS3GmooJW2Fjj7q1kCcaEQbMB1/aQHLXd1qe3KJOzXh3Voxsp/jEH0hvp2TII\nfY9UK+b7mA+xlvXwKuTkHVaZm0ylg0nbembS8MF4GfFMujinSexvLrVKaQhdMFoF\nvBLxHYHRAoGBANfNVYJYeCDPFNLmak5Xg33Rfvc2II8UmrZOVdhOWs8ZK0pis9e+\nPo2MKtTzrzipXI2QXv5w7kO+LJWNDva+xRlW8Wlj9Dde9QdQ7Y8+dk7SJgf24DzM\n023elgX5DvTeLODjStk6SMPRL0FmGovUqAAA8ZeHtJzkIr1HROWnQiwnAoGBANez\nhFwKnVoQu0RpBz/i4W0RKIxOwltN2zmlN8KjJPhSy00A7nBUfKLRbcwiSHE98Yi/\nUrXwMwR5QeD2ngngRppddJnpiRfjNjnsaqeqNtpO8AxB3XjpCC5zmHUMFHKvPpDj\n1zU/F44li0YjKcMBebZy9PbfAjrIgJfxhPo/oXiNAoGAfx6gaTjOAp2ZaaZ7Jozc\nkyft/5et1DrR6+P3I4T8bxQncRj1UXfqhxzzOiAVrm3tbCKIIp/JarRCtRGzp9u2\nZPfXGzra6CcSdW3Rkli7/jBCYNynOIl7XjQI8ZnFmq6phwu80ntH07mMeZy4tHff\nQqlLpvQ0i1rDr/Wkexdsnm8CgYBgxha9ILoF/Xm3MJPjEsxmnYsen/tM8XpIu5pv\nxbhBfQvfKWrQlOcyOVnUexEbVVo3KvdVz0VkXW60GpE/BxNGEGXO49rxD6x1gl87\nh/+CJGZIaYiOxaY5CP2+jcPizEL6yG32Yq8TxD5fIkmLRu8vbxX+aIFclDY1dVNe\n3wt3xQKBgGEL0EjwRch+P2V+YHAhbETPrEqJjHRWT95pIdF9XtC8fasSOVH81cLX\nXXsX1FTvOJNwG9Nk8rQjYJXGTb2O/2unaazlYUwxKwVpwuGzz/vhH/roHZBAkIVT\njvpykpn9QMezEdpzj5BEv01QzSYBPzIh5myrpoJIoSW7py7zFG3h\n-----END RSA PRIVATE KEY-----\n', | ||||||
| 			token: '!00000000000000000000000000000001', | 			token: '!00000000000000000000000000000001', | ||||||
| 			password: '$2a$08$OPESxR2RE/ZijjGanNKk6ezSqGFitqsbZqTjWUZPLhORMKxHCbc4O', // ilovesakurako
 | 			password: '$2a$08$OPESxR2RE/ZijjGanNKk6ezSqGFitqsbZqTjWUZPLhORMKxHCbc4O', // ilovesakurako
 | ||||||
| 			profile: {}, | 			profile: {}, | ||||||
|  |  | ||||||
							
								
								
									
										16
									
								
								tools/migration/node.1522066477.user-account-keypair.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								tools/migration/node.1522066477.user-account-keypair.js
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,16 @@ | ||||||
|  | const { default: User } = require('../../built/api/models/user'); | ||||||
|  | const { generate } = require('../../built/crypto_key'); | ||||||
|  | 
 | ||||||
|  | const updates = []; | ||||||
|  | 
 | ||||||
|  | User.find({}).each(function(user) { | ||||||
|  | 	updates.push(User.update({ _id: user._id }, { | ||||||
|  | 		$set: { | ||||||
|  | 			account: { | ||||||
|  | 				keypair: generate(), | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	})); | ||||||
|  | }).then(function () { | ||||||
|  | 	Promise.all(updates) | ||||||
|  | }).then(process.exit); | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue