Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
03566a9
Upgrade to .Net 6
pinksnafu Jan 25, 2022
235f69b
Update To .net &
pinksnafu Nov 18, 2022
682b54a
Create dependabot.yml
pinksnafu May 19, 2023
4e7aedf
Update dependabot.yml
pinksnafu May 19, 2023
6fd4642
Bump Microsoft.EntityFrameworkCore.Tools from 7.0.0 to 7.0.5
dependabot[bot] May 19, 2023
865d2c0
Bump Moq from 4.18.2 to 4.18.4
dependabot[bot] May 19, 2023
47c5bac
Create codeql.yml
pinksnafu May 19, 2023
a98c69d
Merge pull request #5 from pinksnafu/dependabot/nuget/Moq-4.18.4
pinksnafu May 19, 2023
e5ad5de
Merge pull request #3 from pinksnafu/dependabot/nuget/Microsoft.Entit…
pinksnafu May 19, 2023
41257a1
Bump Microsoft.NET.Test.Sdk from 17.4.0 to 17.6.0
dependabot[bot] May 19, 2023
4c4781a
Bump Microsoft.EntityFrameworkCore.SqlServer from 7.0.0 to 7.0.5
dependabot[bot] May 19, 2023
4e66884
Merge pull request #4 from pinksnafu/dependabot/nuget/Microsoft.NET.T…
pinksnafu May 19, 2023
3965a1c
Bump System.Data.SQLite from 1.0.116 to 1.0.117
dependabot[bot] May 19, 2023
004d887
Merge pull request #1 from pinksnafu/dependabot/nuget/Microsoft.Entit…
pinksnafu May 19, 2023
80aa18c
Merge pull request #2 from pinksnafu/dependabot/nuget/System.Data.SQL…
pinksnafu May 19, 2023
b093e4f
Updates
pinksnafu May 19, 2023
a436285
split storage key and encryption key
rdaunce Jun 15, 2021
da440ed
Fix preview mechanism
rdaunce Jun 15, 2021
dfed3b1
Quote url to fix equal sign breaking outlook client
rdaunce Jun 15, 2021
b462701
Added 2 weeks TTL and defaulted TTL to 1 hour
rdaunce Jun 15, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates

version: 2
updates:
- package-ecosystem: "nuget" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "weekly"
76 changes: 76 additions & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"

on:
push:
branches: [ "master" ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ "master" ]
schedule:
- cron: '42 11 * * 4'

jobs:
analyze:
name: Analyze
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
permissions:
actions: read
contents: read
security-events: write

strategy:
fail-fast: false
matrix:
language: [ 'csharp', 'javascript' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Use only 'java' to analyze code written in Java, Kotlin or both
# Use only 'javascript' to analyze code written in JavaScript, TypeScript or both
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support

steps:
- name: Checkout repository
uses: actions/checkout@v3

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.

# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality


# Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2

# ℹ️ Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun

# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.

# - run: |
# echo "Run, Build Application using script"
# ./location_of_script_within_repo/buildscript.sh

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
with:
category: "/language:${{matrix.language}}"
20 changes: 13 additions & 7 deletions Snappass.NET.UnitTest/Snappass.NET.UnitTest.csproj
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>

<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
<PackageReference Include="Moq" Version="4.13.1" />
<PackageReference Include="System.Data.SQLite" Version="1.0.112" />
<PackageReference Include="xunit" Version="2.4.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
<PackageReference Include="coverlet.collector" Version="1.0.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0" />
<PackageReference Include="Moq" Version="4.18.4" />
<PackageReference Include="System.Data.SQLite" Version="1.0.117" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="3.2.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
Expand Down
6 changes: 3 additions & 3 deletions Snappass.NET.sln
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29411.108
# Visual Studio Version 17
VisualStudioVersion = 17.0.32112.339
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Snappass.NET", "Snappass.NET\Snappass.NET.csproj", "{9D5B2889-491B-4E44-B00D-4DA803197031}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Snappass.NET.UnitTest", "Snappass.NET.UnitTest\Snappass.NET.UnitTest.csproj", "{2B880861-D49F-4C86-AB15-67BC84D5933A}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Snappass.NET.UnitTest", "Snappass.NET.UnitTest\Snappass.NET.UnitTest.csproj", "{2B880861-D49F-4C86-AB15-67BC84D5933A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down
17 changes: 12 additions & 5 deletions Snappass.NET/Controllers/PasswordController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,23 @@ public PasswordController(IMemoryStore memoryStore, ILogger<PasswordController>
}

[HttpGet]
[HttpPost]
public IActionResult Preview(string key)
{
if (!_memoryStore.Has(key))
(string storageKey, string encryptionKey) = Encryption.ParseToken(key);
if (!_memoryStore.Has(storageKey))
{
_logger.LogWarning($@"password with key {key} requested, but not found");
_logger.LogWarning($@"password with key {storageKey} requested, but not found");
return NotFound();
}
string encryptedPassword = _memoryStore.Retrieve(key);
string decrypted = Encryption.Decrypt(encryptedPassword, key);
return View("Preview", new PreviewModel { Key = decrypted });
if (HttpContext.Request.Method == "POST")
{
string encryptedPassword = _memoryStore.Retrieve(storageKey);
string decrypted = Encryption.Decrypt(encryptedPassword, encryptionKey);
return View("Password", new PreviewModel { Key = decrypted });
}

return View("Preview");
}
}
}
11 changes: 7 additions & 4 deletions Snappass.NET/Controllers/ShareController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,15 @@ public IActionResult Share(string password, string ttl)
"week" => TimeToLive.Week,
"day" => TimeToLive.Day,
"hour" => TimeToLive.Hour,
_ => throw new ArgumentException("Expected week, day or hour"),
"twoweeks" => TimeToLive.TwoWeeks,
_ => throw new ArgumentException("Expected twoweeks, week, day or hour"),
};
TimeToLive timeToLive = Parse(ttl);
(string encryptedPassword, string key) = Encryption.Encrypt(password);
_memoryStore.Store(encryptedPassword, key, timeToLive);
var model = new GeneratedPassword { Key = key, BaseUri = GetBaseUrl() };
string storageKey = Guid.NewGuid().ToString("N").ToUpper();
(string encryptedPassword, string encryptionKey) = Encryption.Encrypt(password);
_memoryStore.Store(encryptedPassword, storageKey, timeToLive);
string token = Encryption.CreateToken(storageKey, encryptionKey);
var model = new GeneratedPassword { Token = token, BaseUri = GetBaseUrl() };
return View("Shared", model);
}
}
Expand Down
25 changes: 25 additions & 0 deletions Snappass.NET/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.

#Depending on the operating system of the host machines(s) that will build or run the containers, the image specified in the FROM statement may need to be changed.
#For more information, please see https://aka.ms/containercompat

FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY ["Snappass.NET/Snappass.NET.csproj", "Snappass.NET/"]
RUN dotnet restore "Snappass.NET/Snappass.NET.csproj"
COPY . .
WORKDIR "/src/Snappass.NET"
RUN dotnet build "Snappass.NET.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "Snappass.NET.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "Snappass.NET.dll"]
38 changes: 30 additions & 8 deletions Snappass.NET/Encryption.cs
Original file line number Diff line number Diff line change
@@ -1,25 +1,47 @@
using System;
using System.Net;
using Fernet;

namespace Snappass
{
public class Encryption
{
public static (string encryptedPassword, string key) Encrypt(string password)
private static readonly char tokenSeparator = '~';

public static (string encryptedPassword, string encryptionKey) Encrypt(string password)
{
byte[] keyBytes = SimpleFernet.GenerateKey().UrlSafe64Decode();
byte[] EncryptionKeyBytes = SimpleFernet.GenerateKey().UrlSafe64Decode();
var passwordBytes = System.Text.Encoding.Unicode.GetBytes(password);
string encrypted = SimpleFernet.Encrypt(keyBytes, passwordBytes);
string key = keyBytes.UrlSafe64Encode();
return (encrypted, key);
string encryptedPassword = SimpleFernet.Encrypt(EncryptionKeyBytes, passwordBytes);
string encryptionKey = EncryptionKeyBytes.UrlSafe64Encode();
return (encryptedPassword, encryptionKey);
}

public static string Decrypt(string encrypted, string key)
public static string Decrypt(string encryptedPassword, string encryptionKey)
{
var keyBytes = key.UrlSafe64Decode();
var decryptedBytes = SimpleFernet.Decrypt(keyBytes, encrypted, out DateTime _);
var encryptionKeyBytes = encryptionKey.UrlSafe64Decode();
var decryptedBytes = SimpleFernet.Decrypt(encryptionKeyBytes, encryptedPassword, out DateTime _);
var decrypted = decryptedBytes.UrlSafe64Encode().FromBase64String().Replace("\0", "");
return decrypted;
}

public static (string storageKey, string decryptionKey) ParseToken(string token)
{
var tokenFragments = token.Split(tokenSeparator, 2);
var storageKey = tokenFragments[0];
var decryptionKey = string.Empty;

if (tokenFragments.Length > 1)
decryptionKey = WebUtility.UrlDecode(tokenFragments[1]);

return (storageKey, decryptionKey);
}
public static string CreateToken(string storageKey, string encryptionKey)
{
var token = string.Join(tokenSeparator, storageKey, WebUtility.UrlEncode(encryptionKey));

return token;

}
}
}
12 changes: 8 additions & 4 deletions Snappass.NET/MemoryStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,18 +71,22 @@ public string Retrieve(string key)
TimeToLive.Day => item.StoredDateTime.AddDays(1),
TimeToLive.Week => item.StoredDateTime.AddDays(7),
TimeToLive.Hour => item.StoredDateTime.AddHours(1),
TimeToLive.TwoWeeks => item.StoredDateTime.AddDays(14),
_ => item.StoredDateTime.AddHours(1),
};
DateTime atTheLatest = GetAtTheLatest(item.TimeToLive);
if (_dateTimeProvider.Now > atTheLatest)
{
static string ToString(TimeToLive ttl) => ttl switch
{
TimeToLive.Week => "week",
TimeToLive.Day => "day",
TimeToLive.Hour => "hour",
TimeToLive.Week => "1 week",
TimeToLive.Day => "1 day",
TimeToLive.Hour => "1 hour",
TimeToLive.TwoWeeks => "2 weeks",
_ => "1 hour",
};
var ttlString = ToString(item.TimeToLive);
_logger.Log(LogLevel.Warning, $@"Tried to retrieve password for key [{key}] after date is expired. Key set at [{item.StoredDateTime}] for 1 [{ttlString}]");
_logger.Log(LogLevel.Warning, $@"Tried to retrieve password for key [{key}] after date is expired. Key set at [{item.StoredDateTime}] for [{ttlString}]");
_items.Remove(key); // ensure "read-once" is implemented
return null;
}
Expand Down
4 changes: 2 additions & 2 deletions Snappass.NET/Models/GeneratedPassword.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
{
public class GeneratedPassword
{
public string Key { get; set; }
public string Token { get; set; }
public string BaseUri { get; set; }
public string Uri => $@"{BaseUri}/Password/{Key}";
public string Uri => $@"{BaseUri}/Password/{Token}";
}
}
3 changes: 3 additions & 0 deletions Snappass.NET/Properties/serviceDependencies.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"dependencies": {}
}
3 changes: 3 additions & 0 deletions Snappass.NET/Properties/serviceDependencies.local.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"dependencies": {}
}
18 changes: 10 additions & 8 deletions Snappass.NET/Snappass.NET.csproj
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
<AssemblyName>Snappass.NET</AssemblyName>
<RootNamespace>Snappass</RootNamespace>
<OutputType>Exe</OutputType>
<StartupObject></StartupObject>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Dapper" Version="2.0.30" />
<PackageReference Include="Dapper" Version="2.0.123" />
<PackageReference Include="Fernet" Version="0.1.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.0.0">
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.5" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="3.0.0" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="3.0.0" />
<PackageReference Include="System.Data.SQLite" Version="1.0.112" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="7.0.0" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="7.0.6" />
<PackageReference Include="System.Data.SQLite" Version="1.0.117" />
</ItemGroup>

<ItemGroup>
Expand Down
11 changes: 7 additions & 4 deletions Snappass.NET/SqliteStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public override TimeToLive Parse(object value)
0 => TimeToLive.Hour,
1 => TimeToLive.Day,
2 => TimeToLive.Week,
3 => TimeToLive.TwoWeeks,
_ => TimeToLive.Hour,
};
}
Expand Down Expand Up @@ -103,20 +104,22 @@ FROM SECRET
TimeToLive.Day => dateTime.AddDays(1),
TimeToLive.Week => dateTime.AddDays(7),
TimeToLive.Hour => dateTime.AddHours(1),
TimeToLive.TwoWeeks => dateTime.AddDays(14),
_ => dateTime.AddHours(1)
};
DateTime atTheLatest = GetAtTheLatest(secret.TimeToLive, secret.StoredDateTime);
if (_dateTimeProvider.Now > atTheLatest)
{
static string ToString(TimeToLive ttl) => ttl switch
{
TimeToLive.Week => "week",
TimeToLive.Day => "day",
TimeToLive.Hour => "hour",
TimeToLive.Week => "1 week",
TimeToLive.Day => "1 day",
TimeToLive.Hour => "1 hour",
TimeToLive.TwoWeeks => "2 weeks",
_ => "hour"
};
var ttlString = ToString(secret.TimeToLive);
_logger.Log(LogLevel.Warning, $@"Tried to retrieve password for key [{key}] after date is expired. Key set at [{secret.StoredDateTime}] for 1 [{ttlString}]");
_logger.Log(LogLevel.Warning, $@"Tried to retrieve password for key [{key}] after date is expired. Key set at [{secret.StoredDateTime}] for [{ttlString}]");
Remove(key);
return null;
}
Expand Down
2 changes: 1 addition & 1 deletion Snappass.NET/TimeToLive.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
{
public enum TimeToLive
{
Week, Day, Hour
Week, Day, Hour, TwoWeeks
}
}
Loading