Passing a password into the pdf security handler - c#

I'm currently working on a project where pdf's can be decrypted after a successful api call that returns the password.
I've browsed through SO and pdftron SDK but can't find a definitive solution on how to insert this password into the security handler.
Things I have tried:
None of the GetSecurityHandler() methods seem to handle password insertion:
SecurityHandler handler = m_PdfDocument.GetSecurityHandler();
Takes a password string but throws error:
m_PdfDocument.InitStdSecurityHandler(pwd);
error: Message: Not a standard security handler. The custom filter needs to be registered.
Judging from the message I assumed I needed m_PdfDocument.InitSecurityHandler() instead, but that method doesn't take a string, only int.
Anyone can bump me onto the right track ?

Thank you for sending the file. This file is encrypted using custom encryption. Your DRM. No PDF reader can open the file, but your own custom PDF reader.
To open the PDF with PDFNet, you need to find out how the file was encrypted in the first place, and essentially do the opposite. I assume the other team that did the encryption was also decrypting, for at least testing purposes?
It might as simple as following example 3 in our Encryption sample. In which case you just need to register under the filter name that the other team used. I think I know what that is, but won't post here, and will email you instead.
But for others, if the PDF was encrypted with a filter called "Frodo", then it would be
CreateDelegate frodo_del = new CreateDelegate(FrodoSecurityHandler.Create);
SecurityManagerSingleton.Instance().RegisterSecurityHandler("Frodo", new SecurityDescriptor("Frodo Security", frodo_del));

Well according to this page, GetSecurityHandler() is used after you initialize another handler, so since InitSecurityHandler() takes an int you could do this
string password = "9quali52ty3";
// Convert the string into a byte[].
byte[] asciiBytes = Encoding.ASCII.GetBytes(password);
string compiledBytes = System.Text.Encoding.ASCII.GetString(asciiBytes);
int convertedBytes = int.Parse(compiledBytes);
m_PdfDocument.InitSecurityHandler(convertedBytes);
m_PdfDocument.GetSecurityHandler();
A good rule of thumb for programming: There is always a way to get from one datatype to another.
Credit to: #Brig Lamoreaux, #Zanoni and #Brandon on the following pages.
Brig Zanoni Brandon

Related

how can I Implement this c# code in python

the following uses the System.Security.Cryptography namespace from c#
and implements the unprotect method from the ProtectedData class
byte[] output = ProtectedData.Unprotect(input, null, DataProtectionScope.LocalMachine);
I'm trying to access my pc's HKEY_LOCALMACHINE registry with python because theres a key somewhere in it that i need (to read), in order to decrypt a file.
I read the docs but I'm still just not sure what method I should use for that purpose
aReg = winreg.ConnectRegistry(None, HKEY_LOCAL_MACHINE)
I'm not quite sure what comes next so any help would be appreciated.
Turns out I needed this: https://learn.microsoft.com/en-us/windows/win32/api/dpapi/nf-dpapi-cryptunprotectdata
import win32crypt
#open binary file in readmode
filecontents = fileObject.read()
unecryptedFileContents = win32crypt.CryptUnprotectData(filecontents)

How to read file in C# from POST data from web

Basically, I'm building a website that allows user to upload file.
From the front end (JavaScript), the user will browse a file, I can get the site to send POST data (the parameter "UploadInput" and it's value, which the value is the file)
In the backend (C#), I want to make a copy of the file and save it in a specific path.
Below is the way I did it.
var files = Request.Files;
file[0].SaveAs("\temp\\" + file[0].FileName);
The problem I ran into is that I got the error message saying index out of range. I tried Response.Write(files.Count) and it gives me 0 instead of 1.
I'm wondering where I did wrong and how to fix it, or if there's a better way of doing it.
Thanks!
Edit:
I am using HttpFox to debug. From HttpFox, I can see that under POST data, parameter is "UploadInput" and the value is "test.txt"
Edit 2:
So I tried the way Marc provides, and I have a different problem.
I am able to create a new file, however, the content is not copied over. I tried opening the new created file in notepad and all it says is "UploadInput = test.txt"
If they simply posted the file as the body content, then there will be zero "files" involved here, so file[0] will fail. Instead, you need to look at the input-stream, and simply read from that stream. For example:
using(var file = File.Create(somePath)) {
Request.InputStream.CopyTo(file);
}

Lotus Domino: How can I add a department's signature to an email sent through C# using Domino.dll

I'm writing a program where I can send mails (using domino.dll) from three different department mailboxes (each using its own mail server and nsf-file).
All three department mailboxes have a predefined mail signature such as
Regards
Department X
Since those can change anytime I don't want to hardcode the signature in my program but extract them from the mailbox/nsf-file instead and append it to the mail body (or something else if there are better approaches).
I've been looking around all day without finding a solution to this problem, so my question is: How is this achieved?
So far my code is similar to this:
public Boolean sendNotesMail(String messageText)
{
//Create new notes session
NotesSession _notesSession = new NotesSession();
//Initialize Notes Database to null;
NotesDatabase _notesDataBase = null;
//Initialize Notes Document to null;
NotesDocument _notesDocument = null;
string mailServer = #"Path/DDB";
string mailFile = #"Deparmentmail\number.nsf";
//required for send, since its byRef and not byVal, gets set later.
object oItemValue = null;
// Start the connection to Notes. Otherwise log the error and return false
try
{
//Initialize Notes Session
_notesSession.Initialize("");
}
catch
{
//Log
}
// Set database from the mailServer and mailFile
_notesDataBase = _notesSession.GetDatabase(mailServer, mailFile, false);
//If the database is not already open then open it.
if (!_notesDataBase.IsOpen)
{
_notesDataBase.Open();
}
//Create the notes document
_notesDocument = _notesDataBase.CreateDocument();
//Set document type
_notesDocument.ReplaceItemValue("Form", "Memo");
//sent notes memo fields (To and Subject)
_notesDocument.ReplaceItemValue("SendTo", emailAddress);
_notesDocument.ReplaceItemValue("Subject", subjectText);
// Needed in order to send from a departmental mailbox
_notesDocument.ReplaceItemValue("Principal", _notesDataBase.Title);
//Set the body of the email. This allows you to use the appendtext
NotesRichTextItem _richTextItem = _notesDocument.CreateRichTextItem("Body");
// Insert the text to the body
_richTextItem.AppendText(messageText);
try
{
_notesDocument.Send(false, ref oItemValue);
}
}
EDIT:
Thanks to Richard Schwartz my solution is:
object signature = _notesDataBase.GetProfileDocument("calendarprofile", "").GetItemValue("Signature");
String[] stringArray = ((IEnumerable)signature).Cast<object>().Select(x => x.ToString()).ToArray();
_richTextItem.AppendText(stringArray[0]);
The signature is stored in a profile document in the NSF file. You can use the method NotesDatabase.getProfileDocument() to access it. This method takes two arguments:
ProfileName: The profile document name that you need to find the signature is "calendarprofile". (Yes, that's right. It's actually a common profile for many functions, but the calendar developers got there first and named it. ;-))
UniqueKey: Leave this as an empty string. (It is traditionally used to store a username in profile documents in shared databases, but not used in the calendarprofile doc in the mail file.)
You access data in the profile document the same way that you access them in regular documents, e.g., using getItem(), getItemValue(), etc. For a simple text signature, the NotesItem that you are looking for is called "Signature". I notice, however, that there are also items called "Signature_1" and "Signature_2", and "SignatureOption".
If you look at the Preferences UI for setting signatures in Notes mail, you will see that there is a choice between simple text and HTML or graphic files. No doubt this choice will be reflected in the SignatureOption item, so you will probably want to check that first. I have not explored where the data goes if you use imported HTML or graphic files, so I can't say for sure whether it goes into Signature, Signature_1, Signature_2, or somewhere else. But you can explore that on your own by using NotesPeek. You can download it here. It presents a tree-style view of the NSF file. There's a branch of the tree for Profiles, and you can find the calendarprofile there. Then just play around with different settings in the Notes mail preferences and see what changes. (NotesPeek doesn't pick up changes on the fly. You have to close and re-open the profile in NotesPeek after saving changes in the Notes mail preferences dialog in order to see the changes.)
If this gets too difficult, and you want a standard solution for all mails, you might consider this product or a similar one.

File archiving library/API?

I'm making an application where a document is going to depend on resources and I want them to be embeded into one file. Instead of creating a new format, I was wondering if there was a library or API that already exists to create files with other files embeded in them. It doesn't matter what format it is but I'm looking for one with:
OPTION to encrypt or not encrypt
Can tell wether an existing file is already encrypted or not.
Let's me make my own file extension for it, instead of using one that was created for the format.
Works with .NET 3.5
Are there any libs that you guys would recommend?
You could use DotNetZip library, here is the example using AES encryption
using (ZipFile zip = new ZipFile())
{
zip.AddFile("ReadMe.txt"); // no password for this one
zip.Password= "Cool.Hand.Luke!";
zip.Encryption= EncryptionAlgorithm.WinZipAes256;
zip.AddFile("Rawdata-2008-12-18.csv");
zip.Save("Backup-AES-Encrypted.zip");
}
example is from this page, and when saving you can use any extension you wish.
I'm not sure what you mean by "creating your own format".
There are many ways to archive/encrypt files. You can combine these methods. First encrypt whatever you want to write, and then use an API to write them.
Here are a few resources to create archives:
http://weblogs.asp.net/jgalloway/archive/2007/10/25/creating-zip-archives-in-net-without-an-external-library-like-sharpziplib.aspx
For encryption you can use RSA. Replace your_rsa_key with your RSA key.
var provider = new System.Security.Cryptography.RSACryptoServiceProvider();
provider.ImportParameters(your_rsa_key);
var encryptedBytes = provider.Encrypt(
System.Text.Encoding.UTF8.GetBytes("Hello World!"), true);
string decryptedTest = System.Text.Encoding.UTF8.GetString(
provider.Decrypt(encryptedBytes, true));

Unable to verify body hash for DKIM

I'm writing a C# DKIM validator and have come across a problem that I cannot solve. Right now I am working on calculating the body hash, as described in Section 3.7 Computing the Message Hashes. I am working with emails that I have dumped using a modified version of EdgeTransportAsyncLogging sample in the Exchange 2010 Transport Agent SDK. Instead of converting the emails when saving, it just opens a file based on the MessageID and dumps the raw data to disk.
I am able to successfully compute the body hash of the sample email provided in Section A.2 using the following code:
SHA256Managed hasher = new SHA256Managed();
ASCIIEncoding asciiEncoding = new ASCIIEncoding();
string rawFullMessage = File.ReadAllText(#"C:\Repositories\Sample-A.2.txt");
string headerDelimiter = "\r\n\r\n";
int headerEnd = rawFullMessage.IndexOf(headerDelimiter);
string header = rawFullMessage.Substring(0, headerEnd);
string body = rawFullMessage.Substring(headerEnd + headerDelimiter.Length);
byte[] bodyBytes = asciiEncoding.GetBytes(body);
byte[] bodyHash = hasher.ComputeHash(bodyBytes);
string bodyBase64 = Convert.ToBase64String(bodyHash);
string expectedBase64 = "2jUSOH9NhtVGCQWNr9BrIAPreKQjO6Sn7XIkfJVOzv8=";
Console.WriteLine("Expected hash: {1}{0}Computed hash: {2}{0}Are equal: {3}",
Environment.NewLine, expectedBase64, bodyBase64, expectedBase64 == bodyBase64);
The output from the above code is:
Expected hash: 2jUSOH9NhtVGCQWNr9BrIAPreKQjO6Sn7XIkfJVOzv8=
Computed hash: 2jUSOH9NhtVGCQWNr9BrIAPreKQjO6Sn7XIkfJVOzv8=
Are equal: True
Now, most emails come across with the c=relaxed/relaxed setting, which requires you to do some work on the body and header before hashing and verifying. And while I was working on it (failing to get it to work) I finally came across a message with c=simple/simple which means that you process the whole body as is minus any empty CRLF at the end of the body. (Really, the rules for Body Canonicalization are quite ... simple.)
Here is the real DKIM email (right click and save it, the browsers eat the ending CRLF) with a signature using the simple algorithm (completely unmodified). Now, using the above code and updating the expectedBase64 hash I get the following results:
Expected hash: VnGg12/s7xH3BraeN5LiiN+I2Ul/db5/jZYYgt4wEIw=
Computed hash: ISNNtgnFZxmW6iuey/3Qql5u6nflKPTke4sMXWMxNUw=
Are equal: False
The expected hash is the value from the bh= field of the DKIM-Signature header. Now, the file used in the second test is a direct raw output from the Exchange 2010 Transport Agent. If so inclined, you can view the modified EdgeTransportLogging.txt.
At this point, no matter how I modify the second email, changing the start position or number of CRLF at the end of the file I cannot get the files to match. What worries me is that I have been unable to validate any body hash so far (simple or relaxed) and that it may not be feasible to process DKIM through Exchange 2010.
I tried this in python-dkim and I get a body hash mismatch too.
I think probably Exchange's GetMimeReadStream is not giving you the actual bytes as they were transmitted, therefore the hash doesn't match. Probably it's disassembling the message into its mime parts, and then GetMimeReadStream gives you a valid representation of the message, but not the one it was originally sent with.
Perhaps there's another API that will give you the real raw bytes?
Or perhaps by this point in the process the message has been torn apart and the original message thrown away, and you need to hook in earlier.
Probably you should try intercepting a DKIM-signed message by sending it to a non-Exchange server, and see if that works with your code. GetContentReadStream might possibly work?
Anyhow, what I would do next is try to find an API that gives you byte-for-byte what was sent.

Categories