Skip to content

Commit

Permalink
fix/simplify encryption and add workspace detection
Browse files Browse the repository at this point in the history
  • Loading branch information
elasticroentgen committed Apr 22, 2024
1 parent 01799c4 commit b68ed5c
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 221 deletions.
197 changes: 25 additions & 172 deletions FileProcessor.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
using System.Security.Cryptography;
using System.Text;
using Org.BouncyCastle.Bcpg;
using Org.BouncyCastle.Bcpg.OpenPgp;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using PgpCore;
using SharpCompress.Common;
using SharpCompress.Writers;

Expand All @@ -19,178 +14,36 @@ public void CreateTarGz(string outputPath, string inputDirectory)
writer.WriteAll(inputDirectory, searchPattern: "*", SearchOption.AllDirectories);
}

public static void DecryptFileSymetric(string inputFile, string outputFile, string password)
public async Task EncryptFilePgp(string inputFile, string publicKeyFile, string outputFile)
{
byte[] passwordBytes = System.Text.Encoding.UTF8.GetBytes(password);
byte[] salt = new byte[32];

FileStream fsCrypt = new FileStream(inputFile, FileMode.Open);
fsCrypt.Read(salt, 0, salt.Length);

Rfc2898DeriveBytes derivedBytes = new Rfc2898DeriveBytes(passwordBytes, salt, 50000, HashAlgorithmName.SHA256);
Aes aes = Aes.Create();
aes.KeySize = 256;
aes.BlockSize = 128;
aes.Key = derivedBytes.GetBytes(aes.KeySize / 8);
aes.IV = derivedBytes.GetBytes(aes.BlockSize / 8);

CryptoStream cs = new CryptoStream(fsCrypt, aes.CreateDecryptor(), CryptoStreamMode.Read);
FileStream fsOut = new FileStream(outputFile, FileMode.Create);

int read;
byte[] buffer = new byte[1048576];

try
{
while ((read = cs.Read(buffer, 0, buffer.Length)) > 0)
{
fsOut.Write(buffer, 0, read);
}
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
}

try
{
cs.Close();
}
catch (Exception ex)
{
Console.WriteLine("Error by closing CryptoStream: " + ex.Message);
}
finally
{
fsOut.Close();
fsCrypt.Close();
}
// Load key
FileInfo publicKey = new FileInfo(publicKeyFile);
EncryptionKeys encryptionKeys = new EncryptionKeys(publicKey);

// Get file infos
FileInfo inputFileInfo = new FileInfo(inputFile);
FileInfo encryptedSignedFile = new FileInfo(outputFile);
// Encrypt and Sign
PGP pgp = new PGP(encryptionKeys);
pgp.SymmetricKeyAlgorithm = SymmetricKeyAlgorithmTag.Aes256;
await pgp.EncryptFileAsync(inputFileInfo, encryptedSignedFile);
}


public void EncryptFileSymetric(string inputFile, string outputFile, string pgpKeyFile)
public async Task DecryptFilePgp(string inputFilePath, string outputFilePath, string privateKeyPath, string password)
{
byte[] salt = RandomNumberGenerator.GetBytes(32);
string randomPassword = RandomNumberGenerator.GetHexString(128);
// Load keys
EncryptionKeys encryptionKeys;
await using (Stream privateKeyStream = new FileStream(privateKeyPath, FileMode.Open))
encryptionKeys = new EncryptionKeys(privateKeyStream, password);

// Encrypt password with Pgp
Console.WriteLine($"Password used: {randomPassword}");

EncryptStringPgp(randomPassword, pgpKeyFile, $"{outputFile}.key");

FileStream fsCrypt = new FileStream(outputFile, FileMode.Create);

byte[] passwordBytes = System.Text.Encoding.UTF8.GetBytes(randomPassword);
Rfc2898DeriveBytes derivedBytes = new Rfc2898DeriveBytes(passwordBytes, salt, 50000, HashAlgorithmName.SHA256);
Aes aes = Aes.Create();
aes.KeySize = 256;
aes.BlockSize = 128;
aes.Key = derivedBytes.GetBytes(aes.KeySize / 8);
aes.IV = derivedBytes.GetBytes(aes.BlockSize / 8);

fsCrypt.Write(salt, 0, salt.Length);
// Get file infos
FileInfo inputFileInfo = new FileInfo(inputFilePath);
FileInfo outputFileInfo = new FileInfo(outputFilePath);

CryptoStream cs = new CryptoStream(fsCrypt, aes.CreateEncryptor(), CryptoStreamMode.Write);
FileStream fsIn = new FileStream(inputFile, FileMode.Open);
PGP pgp = new PGP(encryptionKeys);
pgp.SymmetricKeyAlgorithm = SymmetricKeyAlgorithmTag.Aes256;

byte[] buffer = new byte[1048576];

Console.Write("Encrypting file.");
try
{
int read;
while ((read = fsIn.Read(buffer, 0, buffer.Length)) > 0)
{
cs.Write(buffer, 0, read);
Console.Write(".");
}

fsIn.Close();
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
}
finally
{
cs.Close();
fsCrypt.Close();
}

Console.WriteLine("done");
// Reference input/output files
await pgp.DecryptFileAsync(inputFileInfo, outputFileInfo);
}


public void EncryptFilePGP(string inputFile, string publicKeyFile, string outputFile, bool armor, bool withIntegrityCheck)
{
using Stream publicKeyStream = File.OpenRead(publicKeyFile);
PgpPublicKey encKey = ReadPublicKey(publicKeyStream);

using MemoryStream bOut = new MemoryStream();
PgpCompressedDataGenerator comData = new PgpCompressedDataGenerator(CompressionAlgorithmTag.Zip);

PgpUtilities.WriteFileToLiteralData(
comData.Open(bOut),
PgpLiteralData.Binary,
new FileInfo(inputFile));

comData.Close();

PgpEncryptedDataGenerator cPk = new PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag.Cast5, withIntegrityCheck, new SecureRandom());

cPk.AddMethod(encKey);

byte[] bytes = bOut.ToArray();

using Stream outputStream = File.Create(outputFile);
if (armor)
{
using Stream armoredStream = new ArmoredOutputStream(outputStream);
WriteBytesToStream(cPk.Open(armoredStream, bytes.Length), bytes);
}
else
{
WriteBytesToStream(cPk.Open(outputStream, bytes.Length), bytes);
}
}

public void EncryptStringPgp(string inputString, string publicKeyFile, string outputFile)
{
using Stream publicKeyStream = File.OpenRead(publicKeyFile);
PgpPublicKey encKey = ReadPublicKey(publicKeyStream);

PgpEncryptedDataGenerator cPk = new PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag.Cast5, true, new SecureRandom());
cPk.AddMethod(encKey);

byte[] bytes = Encoding.UTF8.GetBytes(inputString);

using Stream outputStream = File.Create(outputFile);
using Stream armoredStream = new ArmoredOutputStream(outputStream);
WriteBytesToStream(cPk.Open(armoredStream, bytes.Length), bytes);
}
private static void WriteBytesToStream(Stream outputStream, byte[] bytes)
{
using Stream encryptedOut = outputStream;
encryptedOut.Write(bytes, 0, bytes.Length);
}

private static PgpPublicKey ReadPublicKey(Stream inputStream)
{
using Stream keyIn = inputStream;
PgpPublicKeyRingBundle pgpPub = new PgpPublicKeyRingBundle(PgpUtilities.GetDecoderStream(keyIn));

foreach (PgpPublicKeyRing keyRing in pgpPub.GetKeyRings())
{
foreach (PgpPublicKey key in keyRing.GetPublicKeys())
{
if (key.IsEncryptionKey)
{
return key;
}
}
}

throw new ArgumentException("Can't find encryption key in key ring.");
}

}
61 changes: 34 additions & 27 deletions MailGrabber.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,43 +17,50 @@ public MailGrabber(string host, string user, string password)
_password = password;
}

internal List<string> FindUrl(string sender, string regexPattern)
internal List<Tuple<string,string>> FindUrl(string sender, string regexPatternDownload, string regexPatternWorkspace)
{
List<string> urls = new List<string>();
using (var client = new ImapClient())
{
client.ServerCertificateValidationCallback = (s, c, h, e) => true;
client.Connect(_host, 993, true);
client.Authenticate(_user, _password);
using var client = new ImapClient();
client.ServerCertificateValidationCallback = (s, c, h, e) => true;
client.Connect(_host, 993, true);
client.Authenticate(_user, _password);
List<Tuple<string, string>> urls = new List<Tuple<string, string>>();

var inbox = client.Inbox;
inbox.Open(MailKit.FolderAccess.ReadOnly);
var inbox = client.Inbox;
inbox.Open(MailKit.FolderAccess.ReadOnly);

for (int i = 0; i < inbox.Count; i++)
{
MimeMessage? message = inbox.GetMessage(i);
for (int i = 0; i < inbox.Count; i++)
{
MimeMessage? message = inbox.GetMessage(i);

if((message.From[0] as MailboxAddress)?.Address != sender)
continue;
if((message.From[0] as MailboxAddress)?.Address != sender)
continue;

string body = message.HtmlBody;

// Regex to extract URLs
var regex = new Regex(regexPattern, RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Multiline );
string body = message.HtmlBody;

// Find matches
MatchCollection matches = regex.Matches(body);
// Regex to extract URLs
var regexDl = new Regex(regexPatternDownload, RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Multiline );
var regexWorkspace = new Regex(regexPatternWorkspace, RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Multiline );

// Report on each match.
foreach (Match match in matches)
{
urls.Add(match.Value);
}
string dlUrl = String.Empty;
string workspaceUrl = String.Empty;
// Report on each match.
foreach (Match match in regexDl.Matches(body))
{
dlUrl = match.Value;
break;
}

client.Disconnect(true);

foreach (Match match in regexWorkspace.Matches(body))
{
workspaceUrl = match.Value;
break;
}

urls.Add(new Tuple<string, string>(dlUrl,workspaceUrl));
}

client.Disconnect(true);

return urls;

}
Expand Down
1 change: 1 addition & 0 deletions NotionBackupTool.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<PackageReference Include="AWSSDK.S3" Version="3.7.307.9" />
<PackageReference Include="MailKit" Version="4.4.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="PgpCore" Version="6.3.1" />
<PackageReference Include="Selenium.WebDriver" Version="4.19.0" />
<PackageReference Include="SharpCompress" Version="0.36.0" />
</ItemGroup>
Expand Down
5 changes: 3 additions & 2 deletions NotionWebsitePuppeteer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,12 @@ void TryLoginWithLink()
{
Thread.Sleep(2000);
Console.WriteLine("Waiting for login code email...");
List<string> loginUrls = mg.FindUrl("notify@mail.notion.so", "https://www\\.notion\\.so/loginwithemail.*?(?=\")");
List<Tuple<string, string>> loginUrls = mg.FindUrl("notify@mail.notion.so",
"https://www\\.notion\\.so/loginwithemail.*?(?=\")", String.Empty);

if (loginUrls.Count == 0) continue;

loginUrl = loginUrls.First();
loginUrl = loginUrls.First().Item1;
foundUrl = true;
mg.Purge("notify@mail.notion.so","login code");

Expand Down
Loading

0 comments on commit b68ed5c

Please sign in to comment.