Welcome to mirror list, hosted at ThFree Co, Russian Federation.

PWDv1Challenge.js « Challenge « Authorization « src - git.mdns.eu/nextcloud/passwords-client.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 13a3559e19794501e10d95da7ebf9f009c1653be (plain)
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
import sodium from 'libsodium-wrappers';

export default class PWDv1Challenge {

    constructor(data) {
        this._salts = null;
        if(data.hasOwnProperty('salts')) {
            this._salts = data.salts;
        }
        this._password = null;
    }

    /**
     *
     * @returns {null}
     */
    getPassword() {
        return this._password;
    }

    /**
     *
     * @param value
     * @returns {PWDv1Challenge}
     */
    setPassword(value) {
        this._password = value;

        return this;
    }

    /**
     * Generate a challenge solution with the user provided password
     * and the server provided salts
     *
     * @returns {string}
     */
    solve() {
        if(this._password.length < 12) throw new Error('Password is too short');
        if(this._password.length > 128) throw new Error('Password is too long');
        let salts = this._salts;

        let passwordSalt     = sodium.from_hex(salts[0]),
            genericHashKey   = sodium.from_hex(salts[1]),
            passwordHashSalt = sodium.from_hex(salts[2]),
            genericHash      = sodium.crypto_generichash(
                sodium.crypto_generichash_BYTES_MAX,
                new Uint8Array([...sodium.from_string(this._password), ...passwordSalt]),
                genericHashKey
            );

        let passwordHash = sodium.crypto_pwhash(
            sodium.crypto_box_SEEDBYTES,
            genericHash,
            passwordHashSalt,
            sodium.crypto_pwhash_OPSLIMIT_INTERACTIVE,
            sodium.crypto_pwhash_MEMLIMIT_INTERACTIVE,
            sodium.crypto_pwhash_ALG_DEFAULT
        );


        return sodium.to_hex(passwordHash);
    }

    /**
     * Create the salts and the secret for the server
     * using the user provided password
     *
     * @returns {{salts: *[], secret: *}}
     */
    create() {
        if(this._password.length < 12) throw new Error('Password is too short');
        if(this._password.length > 128) throw new Error('Password is too long');

        let passwordSalt   = sodium.randombytes_buf(256),
            genericHashKey = sodium.randombytes_buf(sodium.crypto_generichash_KEYBYTES_MAX),
            genericHash    = sodium.crypto_generichash(
                sodium.crypto_generichash_BYTES_MAX,
                new Uint8Array([...sodium.from_string(this._password), ...passwordSalt]),
                genericHashKey
            );

        let passwordHashSalt = sodium.sodium(sodium.crypto_pwhash_SALTBYTES),
            passwordHash     = sodium.crypto_pwhash(
                sodium.crypto_box_SEEDBYTES,
                genericHash,
                passwordHashSalt,
                sodium.crypto_pwhash_OPSLIMIT_INTERACTIVE,
                sodium.crypto_pwhash_MEMLIMIT_INTERACTIVE,
                sodium.crypto_pwhash_ALG_DEFAULT
            );

        return {
            salts : [
                sodium.to_hex(passwordSalt),
                sodium.to_hex(genericHashKey),
                sodium.to_hex(passwordHashSalt)
            ],
            secret: sodium.to_hex(passwordHash)
        }
    }
}