Skip to content

Commit

Permalink
Merge pull request #112 from pusher/feature/E2E-encryption
Browse files Browse the repository at this point in the history
Feature: end-to-end encryption for private encrypted channels
  • Loading branch information
Jon Elverkilde authored Apr 16, 2021
2 parents 7810cda + 948fdb6 commit 4481174
Show file tree
Hide file tree
Showing 59 changed files with 1,336 additions and 1,187 deletions.
13 changes: 10 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ jobs:
PUSHER_APP_KEY: ${{ secrets.CI_APP_KEY }}
PUSHER_APP_SECRET: ${{ secrets.CI_APP_SECRET }}
PUSHER_APP_CLUSTER: ${{ secrets.CI_APP_CLUSTER }}
run: vstest.console.exe /Parallel /Platform:x64 "./PusherClient.Tests/bin/Release/PusherClient.Tests.dll" /TestAdapterPath:"./PusherClient.Tests/bin/Release/"
- name: Test pack
run: msbuild /t:Pack /p:configuration=release PusherClient/PusherClient.csproj
run: vstest.console.exe /Parallel /Platform:x64 "./PusherClient.Tests/bin/Release/net45/PusherClient.Tests.dll" /TestAdapterPath:"./PusherClient.Tests/bin/Release/net45"
- name: Write code signing key
env:
CI_CODE_SIGN_KEY: ${{ secrets.CI_CODE_SIGN_KEY }}
run: |
./StrongName/WritePusherKey.ps1
- name: Test strong name signing
run: msbuild /p:SignAssembly=true /p:deterministic=true /p:msbuildArchitecture=x64 /p:configuration=Release pusher-dotnet-client.sln
- name: Test pack with strong named assembly
run: msbuild /t:Pack /p:SignAssembly=true /p:configuration=release PusherClient/PusherClient.csproj
9 changes: 7 additions & 2 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,14 @@ jobs:
uses: microsoft/setup-msbuild@v1.0.2
- name: Restore dependencies
run: nuget restore pusher-dotnet-client.sln
- name: Write code signing key
env:
CI_CODE_SIGN_KEY: ${{ secrets.CI_CODE_SIGN_KEY }}
run: |
./StrongName/WritePusherKey.ps1
- name: Build
run: msbuild /p:deterministic=true /p:msbuildArchitecture=x64 /p:configuration=Release pusher-dotnet-client.sln
run: msbuild /p:SignAssembly=true /p:deterministic=true /p:msbuildArchitecture=x64 /p:configuration=Release pusher-dotnet-client.sln
- name: Pack
run: msbuild /t:Pack /p:configuration=release PusherClient/PusherClient.csproj
run: msbuild /t:Pack /p:SignAssembly=true /p:configuration=release PusherClient/PusherClient.csproj
- name: Publish
run: nuget push PusherClient\bin\release\PusherClient.*.nupkg -NonInteractive -Source https://api.nuget.org/v3/index.json -SkipDuplicate -ApiKey ${{ secrets.NUGET_API_KEY }}
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ TestResults/
# Secrets file
AppConfig.test.json

# Signing key
PusherClient.snk

# Custom
_ReSharper.*/
packages/
Expand Down
11 changes: 0 additions & 11 deletions AuthHost/App.config
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,4 @@
<appSettings>
<add key="Port" value="8888" />
</appSettings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.1" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
144 changes: 19 additions & 125 deletions AuthHost/AuthHost.csproj
Original file line number Diff line number Diff line change
@@ -1,134 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{218EE921-5E27-4E15-9382-42DD2F40857C}</ProjectGuid>
<TargetFrameworks>net45</TargetFrameworks>
<IsPackable>false</IsPackable>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>AuthHost</RootNamespace>
<AssemblyName>AuthHost</AssemblyName>
<TargetFrameworkVersion>v4.7.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
<Authors>Pusher</Authors>
<Company>Pusher.com</Company>
<Product>PusherClient</Product>
<Copyright>Copyright © Pusher 2021</Copyright>
<Description>An example authentication host for use with the Pusher example app</Description>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Threading.Tasks, Version=1.0.12.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Threading.Tasks.Extensions, Version=1.0.12.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Threading.Tasks.Extensions.Desktop, Version=1.0.168.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll</HintPath>
</Reference>
<Reference Include="Nancy, Version=1.4.4.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Nancy.1.4.4\lib\net40\Nancy.dll</HintPath>
</Reference>
<Reference Include="Nancy.Hosting.Self, Version=1.4.1.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Nancy.Hosting.Self.1.4.1\lib\net40\Nancy.Hosting.Self.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="PusherServer, Version=4.4.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\PusherServer.4.4.0\lib\net45\PusherServer.dll</HintPath>
</Reference>
<Reference Include="SuperSocket.ClientEngine, Version=0.10.0.0, Culture=neutral, PublicKeyToken=ee9af13f57f00acc, processorArchitecture=MSIL">
<HintPath>..\packages\SuperSocket.ClientEngine.Core.0.10.0\lib\net45\SuperSocket.ClientEngine.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.Configuration" />
<Reference Include="System.Core" />
<Reference Include="System.Linq, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Linq.4.3.0\lib\net463\System.Linq.dll</HintPath>
<Private>True</Private>
<Private>True</Private>
</Reference>
<Reference Include="System.Net" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Runtime, Version=4.1.1.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.4.3.1\lib\net462\System.Runtime.dll</HintPath>
<Private>True</Private>
<Private>True</Private>
</Reference>
<Reference Include="System.Runtime.Extensions, Version=4.1.1.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.Extensions.4.3.1\lib\net462\System.Runtime.Extensions.dll</HintPath>
<Private>True</Private>
<Private>True</Private>
</Reference>
<Reference Include="System.Runtime.InteropServices, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.InteropServices.4.3.0\lib\net463\System.Runtime.InteropServices.dll</HintPath>
<Private>True</Private>
<Private>True</Private>
</Reference>
<Reference Include="System.Text.RegularExpressions, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Text.RegularExpressions.4.3.1\lib\net463\System.Text.RegularExpressions.dll</HintPath>
<Private>True</Private>
<Private>True</Private>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="WebSocket4Net, Version=0.15.2.11, Culture=neutral, PublicKeyToken=eb4e154b696bf72a, processorArchitecture=MSIL">
<HintPath>..\packages\WebSocket4Net.0.15.2\lib\net45\WebSocket4Net.dll</HintPath>
</Reference>
</ItemGroup>

<ItemGroup>
<Compile Include="AuthModule.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="Nancy" Version="1.4.4" />
<PackageReference Include="Nancy.Hosting.Self" Version="1.4.1" />
<PackageReference Include="PusherServer" Version="4.6.0" />
</ItemGroup>

<ItemGroup>
<None Include="App.config" />
<None Include="packages.config" />
<Reference Include="System.Configuration" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\PusherClient.Tests.Utilities\PusherClient.Tests.Utilities.csproj">
<Project>{00f1f3be-1210-4d06-89ca-f1e17898384c}</Project>
<Name>PusherClient.Tests.Utilities</Name>
</ProjectReference>
<ProjectReference Include="..\PusherClient.Tests.Utilities\PusherClient.Tests.Utilities.csproj" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets" Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets'))" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

</Project>
40 changes: 38 additions & 2 deletions AuthHost/AuthModule.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System;
using System.Threading.Tasks;
using Nancy;
using PusherClient;
using PusherClient.Tests.Utilities;
using PusherServer;

Expand All @@ -14,9 +16,16 @@ public class AuthModule : NancyModule

public string PusherApplicationSecret => Config.AppSecret;

public const string EncryptionMasterKeyText = "Rk4twMwEogcmx5dpV+6puT+nNidXoRd3smLvWR57FbQ=";

public AuthModule()
{
var provider = new Pusher(PusherApplicationId, PusherApplicationKey, PusherApplicationSecret);
PusherServer.PusherOptions options = new PusherServer.PusherOptions
{
EncryptionMasterKey = Convert.FromBase64String(EncryptionMasterKeyText),
Cluster = Config.Cluster,
};
var provider = new PusherServer.Pusher(PusherApplicationId, PusherApplicationKey, PusherApplicationSecret, options);

Post["/auth/{username}", ctx => ctx.Request.Form.channel_name && ctx.Request.Form.socket_id] = _ =>
{
Expand All @@ -27,7 +36,7 @@ public AuthModule()

string authData = null;

if (channelName.StartsWith("presence-"))
if (Channel.GetChannelType(channelName) == ChannelTypes.Presence)
{
var channelData = new PresenceChannelData
{
Expand All @@ -42,8 +51,35 @@ public AuthModule()
authData = provider.Authenticate(channelName, socketId).ToJson();
}

if (Channel.GetChannelType(channelName) == ChannelTypes.PrivateEncrypted)
{
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
SendSecretMessageAsync();
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
}

return authData;
};
}

private async Task SendSecretMessageAsync()
{
await Task.Delay(5000).ConfigureAwait(false);
PusherServer.PusherOptions options = new PusherServer.PusherOptions
{
EncryptionMasterKey = Convert.FromBase64String(EncryptionMasterKeyText),
Cluster = Config.Cluster,
};
string channelName = "private-encrypted-channel";
string eventName = "secret-event";
var provider = new PusherServer.Pusher(PusherApplicationId, PusherApplicationKey, PusherApplicationSecret, options);
string secretMessage = $"sent secret at {DateTime.Now} on '{channelName}' using event '{eventName}'.";
await provider.TriggerAsync(channelName, eventName, new
{
Name = nameof(AuthModule),
Message = secretMessage,
}).ConfigureAwait(false);
Console.WriteLine(secretMessage);
}
}
}
36 changes: 0 additions & 36 deletions AuthHost/Properties/AssemblyInfo.cs

This file was deleted.

18 changes: 0 additions & 18 deletions AuthHost/packages.config

This file was deleted.

8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## 2.1.0
* [ADDED] Strong name to the PusherClient assembly.
* [ADDED] Support for the authentication header on the HttpAuthorizer.
* [ADDED] End-to-end encryption for private encrypted channels.
* [ADDED] Method Channel.UnsubscribeAsync.
* [ADDED] Host to PusherOptions.
* [FIXED] The intermittent WebsocketAutoReconnect issue The socket is connecting, cannot connect again!

## 2.0.1
* [FIXED] Filter on event name in event emitter.

Expand Down
15 changes: 0 additions & 15 deletions ExampleApplication/App.config
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.1" />
</startup>
<system.diagnostics>
<sources>
<source name="Pusher" switchValue="Information, Warning, Error">
Expand All @@ -13,16 +10,4 @@
</sources>
<trace autoflush="true" />
</system.diagnostics>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.Extensions" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.1.0" newVersion="4.1.1.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
Loading

0 comments on commit 4481174

Please sign in to comment.