Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] #2543

Open
q-bertsuit opened this issue Sep 13, 2024 · 1 comment · May be fixed by #2557
Open

[BUG] #2543

q-bertsuit opened this issue Sep 13, 2024 · 1 comment · May be fixed by #2557
Labels

Comments

@q-bertsuit
Copy link

q-bertsuit commented Sep 13, 2024

LiteDB version 5.0.21
Microsoft Windows Embedded Standard 6.1.7601.NULL, 64 bit.

We've developed an application in .Net Core 6 that works fine on most machines, but I got a report that it fails with this exception on certain machines:

Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException: Unknown error (0xc1000001)
at Interop.BCrypt.BCryptAlgorithmCache.GetCachedBCryptAlgorithmHandle(String hashAlgorithmId, BCryptOpenAlgorithmProviderFlags flags, Int32& hashSizeInBytes)
at Internal.Cryptography.HashProviderCng..ctor(String hashAlgId, ReadOnlySpan`1 key, Boolean isHmac)
at System.Security.Cryptography.SHA1.Implementation..ctor()
at LiteDB.StringExtensions.Sha1(String value)
at LiteDB.SharedEngine..ctor(EngineSettings settings)
at LiteDB.ConnectionString.CreateEngine(Action`1 engineSettingsAction)
at LiteDB.LiteDatabase..ctor(ConnectionString connectionString, BsonMapper mapper)
at LiteDB.LiteDatabase..ctor(String connectionString, BsonMapper mapper)

I'm starting LiteDb in shared mode, and as the exception shows, something goes wrong when creating the name for the mutex. Any idea what could be causing this?

The error only happens once in a while, and if the app is restarted it typically works fine again

@q-bertsuit q-bertsuit added the bug label Sep 13, 2024
@Joy-less
Copy link
Contributor

Looks like your issue arises from the following code:

var name = Path.GetFullPath(settings.Filename).ToLower().Sha1();
public static string Sha1(this string value)
{
    var data = Encoding.UTF8.GetBytes(value);

    using (var sha = SHA1.Create())
    {
        var hashData = sha.ComputeHash(data);
        var hash = new StringBuilder();

        foreach (var b in hashData)
        {
            hash.Append(b.ToString("X2"));
        }

        return hash.ToString();
    }
}

The .Sha1() seems to be necessary because if you remove it, it tries to create a mutex with an invalid name like Global\c:\users\user\documents\github\litedb\litedb.tests\bin\debug\net8\demo.db.Mutex, so to avoid this it hashes the database filepath with SHA1.

To me that seems like a sketchy workaround, especially when SHA1 has known collisions.

I would avoid hashing entirely by using URL encoding, which I've tested correctly encodes all invalid file path characters:

string name = Uri.EscapeDataString(Path.GetFullPath(settings.Filename).ToLowerInvariant());

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants