Skip to content

Commit

Permalink
Google authenticator import (#23)
Browse files Browse the repository at this point in the history
Import Google Authenticator exports - otpauth-migration string

Use nuget packages to parse data and to create the plugin
Parse otpauth-migration also when doing drag&drop
  • Loading branch information
Rookiestyle authored Oct 14, 2020
1 parent c9295fa commit 29f34b0
Show file tree
Hide file tree
Showing 10 changed files with 394 additions and 48 deletions.
33 changes: 2 additions & 31 deletions plgxcreate.cmd
Original file line number Diff line number Diff line change
@@ -1,40 +1,11 @@
@echo off
set plgxnet=%1
set plgxkp=%2
set plgxos=%3

cls
cd %~dp0

for %%* in (.) do set CurrDirName=%%~nx*
echo Processing %CurrDirName%

echo Deleting existing PlgX folder
rmdir /s /q plgx

echo Creating PlgX folder
mkdir plgx

echo Copying files
xcopy src plgx /s /e /exclude:plgxexclude.txt > nul

echo Compiling PlgX
cd..
cd _KeePass_Release
KeePass.exe --plgx-create "%~dp0plgx" plgx-prereq-net:%plgxnet% -plgx-prereq-kp:%plgxkp% -plgx-prereq-os:%plgxos%
cd ..
cd %CurrDirName%

echo Copying PlgX to KeePass plugin folder
copy plgx.plgx "..\_KeePass_Release\Plugins\%CurrDirName%.plgx"
copy "src\bin\Release\%CurrDirName%.plgx" "..\_KeePass_Release\Plugins\%CurrDirName%.plgx"

echo Releasing PlgX
move /y plgx.plgx "..\_Releases\%CurrDirName%.plgx"

echo Cleaning up
rmdir /s /q plgx

echo Compiled with following minimum requirements:
echo .NET = %plgxnet%
echo KeePass = %plgxkp%
echo OS = %plgxos%
move /y "src\bin\Release\%CurrDirName%.plgx" "..\_Releases\%CurrDirName%.plgx"
36 changes: 36 additions & 0 deletions proto/GoogleAuthenticator_Import.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
syntax = "proto3";
package KeePassOTP;

message GoogleAuthenticatorImport {
enum Algorithm {
ALGORITHM_UNSPECIFIED = 0;
ALGORITHM_SHA1 = 1;
ALGORITHM_SHA256 = 2;
ALGORITHM_SHA512 = 3;
ALGORITHM_MD5 = 4;
}
enum DigitCount {
DIGIT_COUNT_UNSPECIFIED = 0;
DIGIT_COUNT_SIX = 1;
DIGIT_COUNT_EIGHT = 2;
}
enum OtpType {
OTP_TYPE_UNSPECIFIED = 0;
OTP_TYPE_HOTP = 1;
OTP_TYPE_TOTP = 2;
}
message OtpParameters {
bytes secret = 1;
string name = 2;
string issuer = 3;
Algorithm algorithm = 4;
DigitCount digits = 5;
OtpType type = 6;
int64 counter = 7;
}
repeated OtpParameters otp_parameters = 1;
int32 version = 2;
int32 batch_size = 3;
int32 batch_index = 4;
int32 batch_id = 5;
}
127 changes: 127 additions & 0 deletions src/GoogleAuthenticatorImport/GoogleAuthenticatorImport.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
// <auto-generated>
// This file was generated by a tool; you should avoid making direct changes.
// Consider using 'partial classes' to extend these types
// Input: my.proto
// </auto-generated>

#region Designer generated code
#pragma warning disable 0612, 0618, 1591, 3021
namespace KeePassOTP
{

[global::ProtoBuf.ProtoContract()]
public partial class GoogleAuthenticatorImport : global::ProtoBuf.IExtensible
{
private global::ProtoBuf.IExtension __pbn__extensionData;
global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing)
{
return global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing);
}
public GoogleAuthenticatorImport()
{
otp_parameters = new global::System.Collections.Generic.List<OtpParameters>();
OnConstructor();
}

partial void OnConstructor();

[global::ProtoBuf.ProtoMember(1)]
public global::System.Collections.Generic.List<OtpParameters> otp_parameters { get; set; }

[global::ProtoBuf.ProtoMember(2, Name = @"version")]
public int Version { get; set; }

[global::ProtoBuf.ProtoMember(3, Name = @"batch_size")]
public int BatchSize { get; set; }

[global::ProtoBuf.ProtoMember(4, Name = @"batch_index")]
public int BatchIndex { get; set; }

[global::ProtoBuf.ProtoMember(5, Name = @"batch_id")]
public int BatchId { get; set; }

[global::ProtoBuf.ProtoContract()]
public partial class OtpParameters : global::ProtoBuf.IExtensible
{
private global::ProtoBuf.IExtension __pbn__extensionData;
global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing)
{
return global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing);
}
public OtpParameters()
{
Name = "";
Issuer = "";
OnConstructor();
}

partial void OnConstructor();

[global::ProtoBuf.ProtoMember(1, Name = @"secret")]
public byte[] Secret { get; set; }

[global::ProtoBuf.ProtoMember(2, Name = @"name")]
[global::System.ComponentModel.DefaultValue("")]
public string Name { get; set; }

[global::ProtoBuf.ProtoMember(3, Name = @"issuer")]
[global::System.ComponentModel.DefaultValue("")]
public string Issuer { get; set; }

[global::ProtoBuf.ProtoMember(4, Name = @"algorithm")]
public GoogleAuthenticatorImport.Algorithm Algorithm { get; set; }

[global::ProtoBuf.ProtoMember(5, Name = @"digits")]
public GoogleAuthenticatorImport.DigitCount Digits { get; set; }

[global::ProtoBuf.ProtoMember(6, Name = @"type")]
public GoogleAuthenticatorImport.OtpType Type { get; set; }

[global::ProtoBuf.ProtoMember(7, Name = @"counter")]
public long Counter { get; set; }

}

[global::ProtoBuf.ProtoContract()]
public enum Algorithm
{
[global::ProtoBuf.ProtoEnum(Name = @"ALGORITHM_UNSPECIFIED")]
AlgorithmUnspecified = 0,
[global::ProtoBuf.ProtoEnum(Name = @"ALGORITHM_SHA1")]
AlgorithmSha1 = 1,
[global::ProtoBuf.ProtoEnum(Name = @"ALGORITHM_SHA256")]
AlgorithmSha256 = 2,
[global::ProtoBuf.ProtoEnum(Name = @"ALGORITHM_SHA512")]
AlgorithmSha512 = 3,
[global::ProtoBuf.ProtoEnum(Name = @"ALGORITHM_MD5")]
AlgorithmMd5 = 4,
}

[global::ProtoBuf.ProtoContract()]
public enum DigitCount
{
[global::ProtoBuf.ProtoEnum(Name = @"DIGIT_COUNT_UNSPECIFIED")]
DigitCountUnspecified = 0,
[global::ProtoBuf.ProtoEnum(Name = @"DIGIT_COUNT_SIX")]
DigitCountSix = 1,
[global::ProtoBuf.ProtoEnum(Name = @"DIGIT_COUNT_EIGHT")]
DigitCountEight = 2,
}

[global::ProtoBuf.ProtoContract()]
public enum OtpType
{
[global::ProtoBuf.ProtoEnum(Name = @"OTP_TYPE_UNSPECIFIED")]
OtpTypeUnspecified = 0,
[global::ProtoBuf.ProtoEnum(Name = @"OTP_TYPE_HOTP")]
OtpTypeHotp = 1,
[global::ProtoBuf.ProtoEnum(Name = @"OTP_TYPE_TOTP")]
OtpTypeTotp = 2,
}

}

}

#pragma warning restore 0612, 0618, 1591, 3021
#endregion
55 changes: 45 additions & 10 deletions src/KeePassOTP.csproj
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<!-- KeePass PLGX Compiler only can build csharp projects up to csharp version 5 -->
<LangVersion>5</LangVersion>
</PropertyGroup>
<PropertyGroup>
<PlgxKeePassVersion>2.42</PlgxKeePassVersion>
<PlgXOS>
</PlgXOS>
</PropertyGroup>
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
Expand All @@ -19,7 +14,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>KeePassOTP</RootNamespace>
<AssemblyName>KeePassOTP</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkSubset>
</TargetFrameworkSubset>
Expand All @@ -40,12 +35,21 @@
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>
</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>
<PropertyGroup>
<PlgxConfiguration>
<Prerequisites>
<KeePassVersion>2.42</KeePassVersion>
<DotNetVersion>$(TargetFrameworkVersion.Replace('v', ''))</DotNetVersion>
</Prerequisites>
</PlgxConfiguration>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core">
Expand All @@ -62,6 +66,7 @@
<Compile Include="DAO\OTPDAO_DB.cs" />
<Compile Include="DAO\OTPDAO_Entry.cs" />
<Compile Include="DAO\OTPDAO.cs" />
<Compile Include="GoogleAuthenticatorImport\GoogleAuthenticatorImport.cs" />
<Compile Include="HotkeyManager.cs" />
<Compile Include="Migration.cs" />
<Compile Include="Properties\Resources.Designer.cs">
Expand Down Expand Up @@ -117,17 +122,47 @@
<ProjectReference Include="..\..\_KeePass_Source\KeePass\KeePass.csproj">
<Project>{10938016-dee2-4a25-9a5a-8fd3444379ca}</Project>
<Name>KeePass</Name>
<!--
We do use the nuget package protobuf-net
Unfortunately, the dll files created during compile time won't be added to the plgx file
We need to use plgxtool to add them
plgxtools does this using the PlgxReference tag which needs to be inside a ProjectReference
Using the reference to KeePass is a workaround and saves us from doing ExcludeFromPlgx for KeePass
-->
<PlgxReference>bin\Release\protobuf-net.dll</PlgxReference>
<PlgxReference>bin\Release\protobuf-net.Core.dll</PlgxReference>
<PlgxReference>bin\Release\System.Buffers.dll</PlgxReference>
<PlgxReference>bin\Release\System.Collections.Immutable.dll</PlgxReference>
<PlgxReference>bin\Release\System.Memory.dll</PlgxReference>
<PlgxReference>bin\Release\System.Numerics.Vectors.dll</PlgxReference>
<PlgxReference>bin\Release\System.Runtime.CompilerServices.Unsafe.dll</PlgxReference>
<PlgxReference>bin\Release\System.ServiceModel.Primitives.dll</PlgxReference>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="Resources\qr-code.png" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="PlgxTool">
<Version>1.0.0</Version>
<ExcludeFromPlgx />
</PackageReference>
<PackageReference Include="protobuf-net">
<Version>3.0.52</Version>
<ExcludeFromPlgx />
</PackageReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="BeforeBuild" Condition=" '$(Configuration)' == 'Debug' ">
<Exec Command="..\translationcopy.cmd $(Configuration)" />
</Target>
<Target Name="AfterBuild" Condition="'$(Configuration)' == 'ReleasePlgx' ">
<!-- Create plgx file -->
<CallTarget Targets="BuildPlgx" />
<!-- copy translations -->
<Exec Command="..\translationcopy.cmd $(Configuration)" />
<Exec Command="..\plgxcreate.cmd $(TargetFrameworkVersion.Replace('v', '')) $(PlgxKeePassVersion) $(PlgXOS)" />
<!-- Copy plgx file -->
<Exec Command="..\plgxcreate.cmd" />
</Target>
</Project>
32 changes: 31 additions & 1 deletion src/KeePassOTPSetup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Windows.Forms;
using KeePassLib.Security;
using KeePassLib.Utility;
using PluginTools;
using PluginTranslation;

namespace KeePassOTP
Expand Down Expand Up @@ -111,6 +112,24 @@ private void UpdatePreview()
OTP.OTPAuthString = new ProtectedString(true, tbOTPSeed.Text);
InitSettings(true);
}
else if (tbOTPSeed.Text.ToLowerInvariant().StartsWith("otpauth-migration://"))
{
int iCount;
ProtectedString psGoogleAuth = PSConvert.ParseGoogleAuthExport(tbOTPSeed.Text, out iCount);
if ((iCount == 1) && (psGoogleAuth.Length > 0))
{
//tbOTPSeed.Text = psGoogleAuth.ReadString();
OTP.OTPAuthString = psGoogleAuth;
InitSettings(true);
return;
}
tbOTPSeed.Text = string.Empty;

if (iCount > 1) Tools.ShowError(string.Format(PluginTranslate.ErrorGoogleAuthImportCount, iCount.ToString()));
else Tools.ShowError(PluginTranslate.ErrorGoogleAuthImport);
return;
}

else OTP.OTPSeed = new ProtectedString(true, tbOTPSeed.Text);

if (cbOTPFormat.SelectedIndex == 0) OTP.Encoding = KPOTPEncoding.BASE32;
Expand Down Expand Up @@ -254,7 +273,18 @@ private void pbQR_DragDrop(object sender, DragEventArgs e)
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
var f = e.Data.GetData(DataFormats.FileDrop) as string[];
if (f != null) otp = ParseFromImageFile(f[0]);
if (f != null)
{
otp = ParseFromImageFile(f[0]);
if (otp.ReadString().ToLowerInvariant().StartsWith("otpauth-migration://"))
{
int iOTPCount = 0;
try { otp = PSConvert.ParseGoogleAuthExport(otp.ReadString(), out iOTPCount); }
catch { }
if (iOTPCount > 1) Tools.ShowError(string.Format(PluginTranslate.ErrorGoogleAuthImportCount, iOTPCount.ToString()));
else if (iOTPCount == 0) Tools.ShowError(PluginTranslate.ErrorGoogleAuthImport);
}
}
}
if (!IsValidOtpAuth(otp))
{
Expand Down
5 changes: 5 additions & 0 deletions src/PluginTranslation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,11 @@ Open it anytime to check the previous content.
Restoring the data needs to be done manually.";
public static readonly string Placeholder = @"Placeholder:";
public static readonly string PlaceholderAutoSubmit = @"{0} + Enter";
public static readonly string ErrorGoogleAuthImport = @"Error parsing data";
public static readonly string ErrorGoogleAuthImportCount = @"Error parsing data
Expected amount of OTP entries: 1
Found amount of OTP entries: {0}";
#endregion

#region NO changes in this area
Expand Down
4 changes: 2 additions & 2 deletions src/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.16.1")]
[assembly: AssemblyFileVersion("0.16.1")]
[assembly: AssemblyVersion("0.17")]
[assembly: AssemblyFileVersion("0.17")]
Loading

0 comments on commit 29f34b0

Please sign in to comment.