aboutsummaryrefslogtreecommitdiff
path: root/tests/Jellyfin.Server.Implementations.Tests/Cryptography/CryptographyProviderTests.cs
blob: 052bdf740ebdeb49a28a3561e57180950f7e4d44 (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
using System;
using Emby.Server.Implementations.Cryptography;
using MediaBrowser.Model.Cryptography;
using Xunit;

namespace Jellyfin.Server.Implementations.Tests.Cryptography;

public class CryptographyProviderTests
{
    private readonly CryptographyProvider _sut = new();

    [Fact]
    public void CreatePasswordHash_WithPassword_ReturnsHashWithIterations()
    {
        var hash = _sut.CreatePasswordHash("testpassword");

        Assert.Equal("PBKDF2-SHA512", hash.Id);
        Assert.True(hash.Parameters.ContainsKey("iterations"));
        Assert.NotEmpty(hash.Salt.ToArray());
        Assert.NotEmpty(hash.Hash.ToArray());
    }

    [Fact]
    public void Verify_WithValidPassword_ReturnsTrue()
    {
        const string password = "testpassword";
        var hash = _sut.CreatePasswordHash(password);

        Assert.True(_sut.Verify(hash, password));
    }

    [Fact]
    public void Verify_WithWrongPassword_ReturnsFalse()
    {
        var hash = _sut.CreatePasswordHash("correctpassword");

        Assert.False(_sut.Verify(hash, "wrongpassword"));
    }

    [Fact]
    public void Verify_PBKDF2_MissingIterations_ThrowsFormatException()
    {
        var hash = PasswordHash.Parse("$PBKDF2$69F420$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D");

        var exception = Assert.Throws<FormatException>(() => _sut.Verify(hash, "password"));
        Assert.Contains("missing required 'iterations' parameter", exception.Message, StringComparison.Ordinal);
    }

    [Fact]
    public void Verify_PBKDF2SHA512_MissingIterations_ThrowsFormatException()
    {
        var hash = PasswordHash.Parse("$PBKDF2-SHA512$69F420$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D");

        var exception = Assert.Throws<FormatException>(() => _sut.Verify(hash, "password"));
        Assert.Contains("missing required 'iterations' parameter", exception.Message, StringComparison.Ordinal);
    }

    [Fact]
    public void Verify_PBKDF2_InvalidIterationsFormat_ThrowsFormatException()
    {
        var hash = PasswordHash.Parse("$PBKDF2$iterations=abc$69F420$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D");

        var exception = Assert.Throws<FormatException>(() => _sut.Verify(hash, "password"));
        Assert.Contains("invalid 'iterations' parameter", exception.Message, StringComparison.Ordinal);
    }

    [Fact]
    public void Verify_PBKDF2SHA512_InvalidIterationsFormat_ThrowsFormatException()
    {
        var hash = PasswordHash.Parse("$PBKDF2-SHA512$iterations=notanumber$69F420$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D");

        var exception = Assert.Throws<FormatException>(() => _sut.Verify(hash, "password"));
        Assert.Contains("invalid 'iterations' parameter", exception.Message, StringComparison.Ordinal);
    }

    [Fact]
    public void Verify_UnsupportedHashId_ThrowsNotSupportedException()
    {
        var hash = PasswordHash.Parse("$UNKNOWN$69F420$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D");

        Assert.Throws<NotSupportedException>(() => _sut.Verify(hash, "password"));
    }

    [Fact]
    public void GenerateSalt_ReturnsNonEmptyArray()
    {
        var salt = _sut.GenerateSalt();

        Assert.NotEmpty(salt);
    }

    [Theory]
    [InlineData(16)]
    [InlineData(32)]
    [InlineData(64)]
    public void GenerateSalt_WithLength_ReturnsArrayOfSpecifiedLength(int length)
    {
        var salt = _sut.GenerateSalt(length);

        Assert.Equal(length, salt.Length);
    }
}