diff --git a/.gitignore b/.gitignore index 17f9604cb032b67ea95f62d85aadae378612b879..07a3d6cdfe56c17b655809b59d74a5a15b8fbdf4 100644 --- a/.gitignore +++ b/.gitignore @@ -96,3 +96,4 @@ static nohup.log fail2ban updatemaster.sh +.history/ \ No newline at end of file diff --git a/backend/ddl_killer/migrations/0023_securitykeypair.py b/backend/ddl_killer/migrations/0023_securitykeypair.py new file mode 100644 index 0000000000000000000000000000000000000000..0e3b6224ad24e77c34328c6737a6c60589049b69 --- /dev/null +++ b/backend/ddl_killer/migrations/0023_securitykeypair.py @@ -0,0 +1,22 @@ +# Generated by Django 2.2 on 2020-05-26 23:04 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ddl_killer', '0022_user_ddl_alert'), + ] + + operations = [ + migrations.CreateModel( + name='SecurityKeyPair', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_at', models.TimeField(auto_now_add=True)), + ('pri_key', models.CharField(max_length=256)), + ('pub_key', models.CharField(max_length=256)), + ], + ), + ] diff --git a/backend/ddl_killer/models.py b/backend/ddl_killer/models.py index 19302194a65bb200f3e72051cf68ab2fd7aacf9a..57a9023ab949f6f08f743c92916122c8314e30f2 100644 --- a/backend/ddl_killer/models.py +++ b/backend/ddl_killer/models.py @@ -107,4 +107,10 @@ class CourseTask(models.Model): class CourseNote(models.Model): course = models.ForeignKey('Course', on_delete=models.CASCADE) - note = models.ForeignKey('Note', on_delete=models.CASCADE) \ No newline at end of file + note = models.ForeignKey('Note', on_delete=models.CASCADE) + + +class SecurityKeyPair(models.Model): + created_at = models.TimeField(auto_now_add=True) + pri_key = models.CharField(max_length=256) + pub_key = models.CharField(max_length=256) # save pub key for debugging diff --git a/backend/ddl_killer/urls.py b/backend/ddl_killer/urls.py index ea279a0fe8c0f813cc9c45531b83dc55840715ff..fdb4ba36c6e2eee037f3db08ff5f493f86a0390e 100644 --- a/backend/ddl_killer/urls.py +++ b/backend/ddl_killer/urls.py @@ -39,5 +39,5 @@ urlpatterns = [ path(r'q2l/dbchange', views.q2ldbchange), path(r'user//tasks//delete', views.delete_task), path(r'user//settings', views.personal_setting), - + path(r'security/pub-key', views.get_security_public_key), # allow: GET ] diff --git a/backend/ddl_killer/utils/jsDecryopt.py b/backend/ddl_killer/utils/jsDecryopt.py index 808bda35188abe32cee5834931a24932221e0007..a7b937f512f40985c0728ff8c9cec728aae8af1c 100644 --- a/backend/ddl_killer/utils/jsDecryopt.py +++ b/backend/ddl_killer/utils/jsDecryopt.py @@ -3,13 +3,16 @@ import base64 from Crypto import Random from Crypto.Cipher import PKCS1_v1_5 from Crypto.PublicKey import RSA +from ..models import SecurityKeyPair key = b'-----BEGIN RSA PRIVATE KEY-----\nMIICXAIBAAKBgQCt1/hVqW9pxTAp6vbJu5+5myvAF8wvsEqM7FdIAKe5hhD1paQh\nPcG/RkPFzQG1u0jeQcwNJIddhmk/jqAK0v2GbHhVUEw/rQ8AATFxLTitXWhjFPC2\nquAlGRzRby4LALxlWBziGNzKU6BERsI1nawJb1Ifi/+q/qgZMCAGKY1EAwIDAQAB\nAoGABp4Tk8vEWKqGf9RGUYa1AfPc5g4K/r9xono68gm3xnhKt4zSeee+oL7osmQn\nQF3ckzy+PU3V9CdNiXtlrsheveC1l88wgirqg5F80W6DTY9X8ZgYzU8hppyCzuaz\ntNIHaMbTuaHnolIpRMxjwbwZYuA48osefsHr/DiL+VjbgEECQQDJ4v3wuJH85M99\nb13FPLVxLXK+qOV6QNfI5vz/tUiWaxctTPu2w48Ft6tH+fp0i8LSgCW2587vjMK1\nKCLqkxwhAkEA3HC6JHsaCZOsjJKlTuZPDTEfkOSPPk3DN+BWQI6x9xHg8aHdoBxJ\neMkzdEP9Md2MTOKUdGUODKBb1cssF477owJBALb2kvGQNC4fJ7QkM7VG2aEicTU9\nWAs9rNIUFQGhR5GaqDyT4iO2g23JEN+AO21YJE4leQiUeMQ8q1EGeO5iOEECQCyD\njvMi8KUSbvuL+VmvZDMzwj4OCWb5aPx1jrVGm2Va9OOWXhyg2a1MY9mMiSpypIw6\nDORcK7QdBa5scqDnPKUCQFQN75mXm21IMYwnAaiikZatsAoh2BdUQR+GmMVECxf2\nJswmQCyFRcc2wd2bDYvE+7tXkkr2gClVPDf9e2Y4DC4=\n-----END RSA PRIVATE KEY-----' + def creat_key(): """ 生成密钥对 - :return: + + :return: a SecurityKeyPair(Model) """ # 伪随机数的方式生成RSA公私钥对 random_generator = Random.new().read @@ -19,22 +22,38 @@ def creat_key(): # 公钥 pub_key = rsa.publickey().exportKey().decode('utf-8') - # 以列表形式返回密钥对 - return [pri_key, pub_key] + key_pair = SecurityKeyPair.objects.create(pri_key=pri_key, pub_key=pub_key) + return key_pair def decode(input_data): """ 解密数据 - :param input_data: - :param key: + + :param input_data: encoded data. if starts with 'kid:', will use saved pri key :return: """ + + private_key = key # default key to keep compatibility + + try: + # kid:| + if input_data.startswith('kid:'): + data_pair = input_data.split('|') + assert len(data_pair) > 1 + kid, data = int(data_pair[0][4:]), '|'.join(data_pair[1:]) + key_pair = SecurityKeyPair.objects.get(id=kid) + private_key = key_pair.pri_key + input_data = data # hack here, TODO remove it + except Exception as e: + print('[DEBUG] in utils.jsDecryopt.decode: using default private key') + print('[DEBUG] reason:', e) + try: # 分组解密默认长度128 default_length = 128 # 创建私钥对象 - pri_key = RSA.importKey(key.decode('utf-8')) + pri_key = RSA.importKey(private_key) cipher = PKCS1_v1_5.new(pri_key) # 现将base64编码格式的数据解码,然后解密,并用decode转成str input_data_b64 = base64.b64decode(input_data.encode('utf-8')) diff --git a/backend/ddl_killer/views.py b/backend/ddl_killer/views.py index 4de9995a8aff6b14dcdccfe331ad6827c33d0c67..a83e2e06d5c94490d295e8a0e62320f37a8d3ae9 100644 --- a/backend/ddl_killer/views.py +++ b/backend/ddl_killer/views.py @@ -15,6 +15,7 @@ import json import yagmail import traceback from .utils.jsDecryopt import decode as jsDecode +from .utils.jsDecryopt import creat_key as create_js_pub_key from .utils.sendmail import register_mail, edit_mail, participate_mail, resource_mail from .utils.webScrap import updateFromCourse @@ -48,6 +49,20 @@ class Token(): serializer = utsr(self.security_key) return serializer.loads(token, salt=self.salt, max_age=expiration) + +def get_security_public_key(request): + """ + /security/pub-key + + generate temporary security key pair and get public key + :param request: + :return: + """ + key = create_js_pub_key() + response = {'code': 200, 'pub_key': key.pub_key, 'key_id': key.id} + return JsonResponse(response, json_dumps_params={'ensure_ascii': False}, charset='utf_8_sig') + + def create_user(request): #用户注册 response={} try: diff --git a/backend/vue2-forntend/src/api/user.js b/backend/vue2-forntend/src/api/user.js index 05a604859904e9aa5e4a60c774f15885747bd83f..0e393615992dc5c0385b9c8adaa1a865a2864ebf 100644 --- a/backend/vue2-forntend/src/api/user.js +++ b/backend/vue2-forntend/src/api/user.js @@ -77,6 +77,14 @@ export function logout() { }) } +export function getPubKey() { + return request({ + baseURL: '', + url: '/api/security/pub-key', + // url: '/vue-admin-template/user/logout', + method: 'get' + }) +} //@ data:{uid:'17370000'} export function sendAuthCode(data){ return request({ diff --git a/backend/vue2-forntend/src/utils/encrypt.js b/backend/vue2-forntend/src/utils/encrypt.js new file mode 100644 index 0000000000000000000000000000000000000000..b48a5fd49674d8fa8421f1e097f5c8c93fd83657 --- /dev/null +++ b/backend/vue2-forntend/src/utils/encrypt.js @@ -0,0 +1,26 @@ +import { JSEncrypt } from 'jsencrypt' +import { getPubKey } from '@/api/user' + +const pub_key = '-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCt1/hVqW9pxTAp6vbJu5+5myvA\nF8wvsEqM7FdIAKe5hhD1paQhPcG/RkPFzQG1u0jeQcwNJIddhmk/jqAK0v2GbHhV\nUEw/rQ8AATFxLTitXWhjFPC2quAlGRzRby4LALxlWBziGNzKU6BERsI1nawJb1If\ni/+q/qgZMCAGKY1EAwIDAQAB\n-----END PUBLIC KEY-----' + +export async function encrypt(password) { + var encPass = "" + console.log("get in encrypt") + await getPubKey().then(res => { + // console.log(res) + let enc = new JSEncrypt() + // res : {'pub_key': pub_key, 'key_id': key.id} + // console.log("res.key_id: ", res.key_id) + // console.log("pub_key: ", res.pub_key) + enc.setPublicKey(res.pub_key) + encPass = "kid:" + res.key_id + "|" + enc.encrypt(password) + }) + return encPass + +} + +// export function encrypt(password) { +// let enc = new JSEncrypt() +// enc.setPublicKey(pub_key) +// return enc.encrypt(password) +// } \ No newline at end of file diff --git a/backend/vue2-forntend/src/views/Message/index.vue b/backend/vue2-forntend/src/views/Message/index.vue index 3a0bfd7755576216880957fb87730b6f2fb2e5ec..d818148f50e5cc8f7a6d4c0293e189b1b14fefd7 100644 --- a/backend/vue2-forntend/src/views/Message/index.vue +++ b/backend/vue2-forntend/src/views/Message/index.vue @@ -14,7 +14,7 @@ - + import { updateFromCourse } from '@/api/user_task' -// import JSEncrypt from '@/utils/jsencrypt/bin/jsencrypt' -import { JSEncrypt } from 'jsencrypt' +import { encrypt } from '@/utils/encrypt' export default { name: 'updateBtn', @@ -62,19 +61,18 @@ export default { loading : false, username: '', password: '', - pub_key: '-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCt1/hVqW9pxTAp6vbJu5+5myvA\nF8wvsEqM7FdIAKe5hhD1paQhPcG/RkPFzQG1u0jeQcwNJIddhmk/jqAK0v2GbHhV\nUEw/rQ8AATFxLTitXWhjFPC2quAlGRzRby4LALxlWBziGNzKU6BERsI1nawJb1If\ni/+q/qgZMCAGKY1EAwIDAQAB\n-----END PUBLIC KEY-----' - }), methods: { - submit() { + async submit() { this.loading = true - let encrypt = new JSEncrypt() - encrypt.setPublicKey(this.pub_key) - var encPassword = encrypt.encrypt(this.password) - console.log(this.username) + // let encrypt = new JSEncrypt() + // encrypt.setPublicKey(this.pub_key) + // var encPassword = encrypt.encrypt(this.password) + // console.log(this.username) + // console.log(encPassword) + let encPassword = await encrypt(this.password) console.log(encPassword) - updateFromCourse(this.$store.getters.uid, { username: this.username, password: encPassword }).then(res => { this.$emit('updEvent') this.loading = false diff --git a/backend/vue2-forntend/src/views/login/index.vue b/backend/vue2-forntend/src/views/login/index.vue index d59088910aefe4892bbde6fa88d3ef36cba6aa1e..5d6652259f276c8d137afacc4ba40c70d060e466 100644 --- a/backend/vue2-forntend/src/views/login/index.vue +++ b/backend/vue2-forntend/src/views/login/index.vue @@ -60,7 +60,7 @@