@@ -24,7 +24,7 @@ class Migration(migrations.Migration): | |||||
), | ), | ||||
migrations.AddField( | migrations.AddField( | ||||
model_name='lesspassuser', | model_name='lesspassuser', | ||||
name='encryption_key', | |||||
name='user_key', | |||||
field=models.TextField(null=True), | field=models.TextField(null=True), | ||||
), | ), | ||||
migrations.CreateModel( | migrations.CreateModel( | ||||
@@ -31,11 +31,12 @@ class LessPassUser(AbstractBaseUser): | |||||
is_active = models.BooleanField(default=True) | is_active = models.BooleanField(default=True) | ||||
is_admin = models.BooleanField(default=False) | is_admin = models.BooleanField(default=False) | ||||
has_password_profile_encrypted = models.BooleanField(default=False) | has_password_profile_encrypted = models.BooleanField(default=False) | ||||
encryption_key = models.TextField(null=True) | |||||
user_key = models.TextField(null=True) | |||||
objects = LesspassUserManager() | objects = LesspassUserManager() | ||||
USERNAME_FIELD = 'email' | USERNAME_FIELD = 'email' | ||||
REQUIRED_FIELDS = ['email', 'user_key'] | |||||
def get_full_name(self): | def get_full_name(self): | ||||
return self.email | return self.email | ||||
@@ -1,3 +1,5 @@ | |||||
const crypto = require("crypto"); | |||||
function stringToArrayBuffer(string) { | function stringToArrayBuffer(string) { | ||||
const base64String = unescape(encodeURIComponent(string)); | const base64String = unescape(encodeURIComponent(string)); | ||||
const charList = base64String.split(""); | const charList = base64String.split(""); | ||||
@@ -17,7 +19,7 @@ function arrayBufferToHex(arrayBuffer) { | |||||
return str; | return str; | ||||
} | } | ||||
function getAlgorithm(algorithm){ | |||||
function getAlgorithm(algorithm) { | |||||
const algorithms = { | const algorithms = { | ||||
sha1: "SHA-1", | sha1: "SHA-1", | ||||
"sha-1": "SHA-1", | "sha-1": "SHA-1", | ||||
@@ -29,8 +31,17 @@ function getAlgorithm(algorithm){ | |||||
return algorithms[algorithm.toLowerCase()] | return algorithms[algorithm.toLowerCase()] | ||||
} | } | ||||
function encryptKey(key, password) { | |||||
console.log(key, password); | |||||
var cipher = crypto.createCipher('aes-128-cbc', password); | |||||
var new_key = cipher.update(key, 'utf8', 'hex') | |||||
new_key += cipher.final('hex'); | |||||
return new_key; | |||||
} | |||||
module.exports = { | module.exports = { | ||||
stringToArrayBuffer, | stringToArrayBuffer, | ||||
arrayBufferToHex, | arrayBufferToHex, | ||||
getAlgorithm | |||||
getAlgorithm, | |||||
encryptKey | |||||
}; | }; |
@@ -1,4 +1,5 @@ | |||||
const pbkdf2 = require("./pbkdf2"); | const pbkdf2 = require("./pbkdf2"); | ||||
const crypto = require("crypto"); | |||||
function calcEntropy(profile, masterPassword) { | function calcEntropy(profile, masterPassword) { | ||||
const { site, login, options, crypto } = profile; | const { site, login, options, crypto } = profile; | ||||
@@ -10,6 +11,22 @@ function calcEntropy(profile, masterPassword) { | |||||
return pbkdf2(masterPassword, salt, iterations, keylen, digest); | return pbkdf2(masterPassword, salt, iterations, keylen, digest); | ||||
} | } | ||||
function generateUserKey() { | |||||
const { iterations, keylen, digest } = { | |||||
iterations: 100000, | |||||
keylen: 32, | |||||
digest: "sha256" | |||||
}; | |||||
random_key = pbkdf2( | |||||
crypto.randomBytes(16), | |||||
crypto.randomBytes(16), | |||||
iterations, | |||||
keylen, | |||||
digest | |||||
); | |||||
return random_key; | |||||
} | |||||
function isSupported() { | function isSupported() { | ||||
try { | try { | ||||
return calcEntropy( | return calcEntropy( | ||||
@@ -48,5 +65,6 @@ function isSupported() { | |||||
module.exports = { | module.exports = { | ||||
isSupported, | isSupported, | ||||
calcEntropy | |||||
calcEntropy, | |||||
generateUserKey | |||||
}; | }; |
@@ -4,6 +4,9 @@ export default { | |||||
login({ email, password }) { | login({ email, password }) { | ||||
return http.post("/api/auth/jwt/create/", { email, password }); | return http.post("/api/auth/jwt/create/", { email, password }); | ||||
}, | }, | ||||
getLoggedUserInformation() { | |||||
return http.get('/api/auth/users/me'); | |||||
}, | |||||
register({ email, password }) { | register({ email, password }) { | ||||
return http.post("/api/auth/users/", { email, password }); | return http.post("/api/auth/users/", { email, password }); | ||||
}, | }, | ||||
@@ -76,6 +76,10 @@ import User from "../api/user"; | |||||
import { defaultbaseURL } from "../api/default"; | import { defaultbaseURL } from "../api/default"; | ||||
import MasterPassword from "../components/MasterPassword.vue"; | import MasterPassword from "../components/MasterPassword.vue"; | ||||
import message from "../services/message"; | import message from "../services/message"; | ||||
import LessPassVue from "lesspass-pure/src/LessPass.vue"; | |||||
import LessPassEntropy from "lesspass-entropy"; | |||||
import LessPassCrypto from "lesspass-crypto"; | |||||
import { random } from "lodash"; | |||||
export default { | export default { | ||||
data() { | data() { | ||||
@@ -107,6 +111,16 @@ export default { | |||||
this.$store.dispatch("setBaseURL", { baseURL }); | this.$store.dispatch("setBaseURL", { baseURL }); | ||||
User.login({ email: this.email, password: this.password }) | User.login({ email: this.email, password: this.password }) | ||||
.then(response => { | .then(response => { | ||||
User.getLoggedUserInformation().then(response => { | |||||
if (response.data.user_key === null) { | |||||
LessPassEntropy.generateUserKey().then(random_key => { | |||||
const key = LessPassCrypto.encryptKey( | |||||
random_key, | |||||
this.password | |||||
); | |||||
}); | |||||
} | |||||
}); | |||||
this.$store.dispatch("login", response.data); | this.$store.dispatch("login", response.data); | ||||
this.$store.dispatch("cleanMessage"); | this.$store.dispatch("cleanMessage"); | ||||
this.$router.push({ name: "home" }); | this.$router.push({ name: "home" }); | ||||