Can i break Adobe PDF password encryption with RC4/AES 128bits? - passwords

I've encrypted some pdf files with iTextsharp lib and using AES 128bits and key length = 16bytes(protect reading).Can anyone break password or some app can do that?
Thank so much.

You can set 2 kinds of possible "passwords" here:
Read password
Edit/Modify password
Using an "edit password" is not secure at all, because it's possible to read the whole file (even without knowing the password, by using PdfReader.unethicalreading = true;) and then creating a new unencrypted one:
using System.IO;
using iTextSharp.text.pdf;
namespace PdfDecryptorCore
{
public class PasswordDecryptor
{
public string ReadPassword { set; get; }
public string PdfPath { set; get; }
public string OutputPdf { set; get; }
public void DecryptPdf()
{
PdfReader.unethicalreading = true;
PdfReader reader;
if(string.IsNullOrWhiteSpace(ReadPassword))
reader = new PdfReader(PdfPath);
else
reader = new PdfReader(PdfPath, System.Text.Encoding.UTF8.GetBytes(ReadPassword));
using (var stamper = new PdfStamper(reader, new FileStream(OutputPdf, FileMode.Create)))
{
stamper.Close();
}
}
}
}

Related

file.OpenReadStream() Cannot access closed stream error

I want Website users to submit a file through a Web form. Sometimes multiple files. Then these files should be emailed to a specific set of users. I have created an Email Service that accepts a List attachments.
`
public class EmailModel
{
public EmailAddressModel FromUser { get; private set; }
public List<EmailAddressModel> ToAddresses { get; private set; }
public List<EmailAddressModel> CcAddresses { get; private set; }
public List<EmailAddressModel> BccAddresses { get; private set; }
public List<IFormFile> Attachments { get; private set; }
public string Subject { get; private set; }
public string Body { get; private set; }
public bool isHTML { get; private set; }
public EmailModel(EmailAddressModel fromUser, List<EmailAddressModel> toAddresses, List<EmailAddressModel> ccAddresses, List<EmailAddressModel> bccAddresses, List<IFormFile> attachments, string subject, string body, bool isHTML)
{
FromUser = fromUser;
ToAddresses = toAddresses;
CcAddresses = ccAddresses;
BccAddresses = bccAddresses;
Attachments = attachments;
Subject = subject;
Body = body;
this.isHTML = isHTML;
}
}
EmailService Prepare Email Attachments.
private void PrepareEmailAttachments()
{
foreach (IFormFile attachment in Email.Attachments)
{
if (attachment.Length > 0)
{
var stream = attachment.OpenReadStream();
using (MemoryStream mStream = new MemoryStream())
{
stream.CopyTo(mStream);
var data = mStream.ToArray();
Builder.Attachments.Add(attachment.FileName, data);
}
}
}
}
Test Code Snippet
List<IFormFile> Attachments = new List<IFormFile>();
using (var stream = File.OpenRead("TestFile\\Test Document.pdf"))
{
var file = new FormFile(stream, 0, stream.Length, null, Path.GetFileName(stream.Name))
{
Headers = new HeaderDictionary(),
ContentType = "application/pdf"
};
Attachments.Add(file);
}
EmailModel Email = new EmailModel(
From,
To,
CC,
BCC,
Attachments,
"Test Email",
"This is a build test",
true);
`
var stream = attachment.OpenReadStream() I am getting a "Cannot Access a closed stream."
`
Message: 
Test method BA.Common.Tests.SendMail.SendEmail threw exception:
System.ObjectDisposedException: Cannot access a closed Stream.
Stack Trace: 
BufferedFileStreamStrategy.Seek(Int64 offset, SeekOrigin origin)
FileStream.set_Position(Int64 value)
ReferenceReadStream.ctor(Stream inner, Int64 offset, Int64 length)
FormFile.OpenReadStream()
EmailService.PrepareEmailAttachments() line 111
EmailService.SendMail() line 43
SendMail.SendEmail() line 58
`
I am expecting that the attachment gets loaded into the MimeKit to be emailed. I have confirmed that the file is ready in attachment. But I cannot figure out why I can't open the attachment.
One of my good friends answered me via email after seeing my post, but he didn't answer here so I will. It turns out that the error was in my integration test, not my project.
I thought that once I added the file to the (Attachment.Add(file); that I could dispose of the stream. In my test I was closing my stream before loading my EmailModel. Simple fix, but I should have kept working up my stack trace to find the error. Thanks Andrew!

Implementation of an IText's IExternalSignatureContainer with BouncyCastle to manage ECDSA-SHA384 signature

I am trying to implement an IExternalSignatureContainer (itext7) to sign PDF with belgian id card.
There is twa smartcard versions to deal with:
RSA/SHA256 signature
ECDSA/SHA384
I achieved to sign the pdf with the RSA/SHA256 siganture but I am not able to make the same for the ECDSA/SHA384.
Here is the Sign method of the ExternalSignatureContainer:
public byte[] Sign(Stream data)
{
var signCert = this.chain.First();
IssuerAndSerialNumber issuerAndSerialNumber = new IssuerAndSerialNumber(signCert.IssuerDN, signCert.SerialNumber);
var signerGenerator = new SignerInfoGeneratorBuilder().Build(
new BeidSignatureFactory(
(data) => this.Sign(data), // Sign data with the eid-middleware
() => this.GetHashAlgorithm(), // Get the hash algorithm of the id card from the eid-middleware
() => this.GetEncryptionAlgorithm() // Get the encryption algorithm of the id card from the eid-middleware
), signCert);
CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
gen.AddSignerInfoGenerator(signerGenerator);
IX509Store x509CertStore = X509StoreFactory.Create(
"Certificate/Collection",
new X509CollectionStoreParameters(this.chain));
gen.AddCertificates(x509CertStore);
CmsProcessableInputStream cmsProcessableInputStream = new CmsProcessableInputStream(data);
var sigData = gen.Generate(cmsProcessableInputStream, false);
return sigData.GetEncoded();
}
Here is a Custom ISignatureFactory and a custom ISigner that use the eid-middleware to access the begian eid card and use it to sign data.
internal class BeidSignatureFactory : ISignatureFactory
{
private readonly BeidSigner _signer = new BeidSigner();
private readonly BeidSigner.SignatureGenerator _signatureGenerator;
private readonly BeidSigner.AlgorithmGetter _getHashAlgorithm;
private readonly BeidSigner.AlgorithmGetter _getEncryptionAlgorithm;
public BeidSignatureFactory(BeidSigner.SignatureGenerator signatureGenerator, BeidSigner.AlgorithmGetter getHashAlgorithm, BeidSigner.AlgorithmGetter getEncryptionAlgorithm)
{
this._signatureGenerator = signatureGenerator;
this._getEncryptionAlgorithm = getEncryptionAlgorithm;
this._getHashAlgorithm = getHashAlgorithm;
}
public IStreamCalculator CreateCalculator()
{
var signer = new BeidSigner
{
Sign = this._signatureGenerator,
GetEncryptionAlgorithm = this._getEncryptionAlgorithm,
GetHashAlgorithm = this._getHashAlgorithm,
};
signer.Init(true, null);
return new DefaultSignatureCalculator(signer);
}
public object AlgorithmDetails
{
get
{
string encryptionAlgorithm = this._getEncryptionAlgorithm();
string hashAlgorithm = this._getHashAlgorithm();
switch (encryptionAlgorithm)
{
case "RSA":
return new AlgorithmIdentifier(PkcsObjectIdentifiers.Sha256WithRsaEncryption);
case "ECDSA":
return new AlgorithmIdentifier(X9ObjectIdentifiers.ECDsaWithSha384);
default:
return null;
}
}
}
}
internal class BeidSigner : ISigner
{
public delegate byte[] SignatureGenerator(byte[] data);
public delegate string AlgorithmGetter();
private byte[] _input;
public void Init(bool forSigning, ICipherParameters parameters)
{
this.Reset();
}
public void Update(byte input)
{
throw new NotImplementedException();
}
public void BlockUpdate(byte[] input, int inOff, int length)
{
this._input = input.Skip(inOff).Take(length).ToArray();
}
public byte[] GenerateSignature()
{
// This method doesn't exist, you will need to implement your own method here
return this.Sign(this._input);
}
public bool VerifySignature(byte[] signature)
{
throw new NotImplementedException();
}
public void Reset() { }
public string AlgorithmName
{
get
{
return $"{this.GetHashAlgorithm()}with{this.GetEncryptionAlgorithm()}";
}
}
public SignatureGenerator Sign { get; set; }
public AlgorithmGetter GetHashAlgorithm { get; set; }
public AlgorithmGetter GetEncryptionAlgorithm { get; set; }
}
Once the pdf signed with the EDCSA signature, the signature is not validated by acrobat reader "Document altered ro corrupted".
Perhaps I have completaly misunderstood the way tho sign the pdf.
Thanks for your help.

Aggregate Exception Asp.Net Core 5.0

I have an Mvc project which is based on Asp.Net Core 5.0 . I have my own Core Layer and i have my own Photo,Video uploader method which is based my FileRepo class.
Here is my FileModel class:
public class FileModel
{
public int FileID { get; set; }
public string FileName { get; set; }
public string FileType { get; set; }
public string FileExtension { get; set; }
public string FileSlug { get; set; }
public string FilePath { get; set; }
public byte[] Data { get; set; }
}
Here is my File Uploader method :
public interface IFileUploader
{
Task<FileModel> FileUploadToDatabase(List<IFormFile> files);
Task<FileModel> FileUploadToPath(List<IFormFile> files);
Task<bool> FileDeleteFromPath(int id);
}
public class FileUploader : IFileUploader
{
private FileModel _fileModel;
public FileUploader(FileModel fileModel)
{
_fileModel = fileModel;
}
public async Task<FileModel> FileUploadToDatabase(List<IFormFile> files)
{
foreach (var file in files)
{
var fileName = Path.GetFileNameWithoutExtension(file.FileName);
var extension = Path.GetExtension(file.FileName);
_fileModel = new FileModel
{
FileName = fileName,
FileType = file.ContentType
};
using (var dataStream = new MemoryStream())
{
await file.CopyToAsync(dataStream);
_fileModel.Data = dataStream.ToArray();
}
}
return _fileModel;
}
public async Task<FileModel> FileUploadToPath(List<IFormFile> files)
{
foreach (var file in files)
{
var basePath = Path.Combine(Directory.GetCurrentDirectory() + "\\Files\\");
bool basePathExists = Directory.Exists(basePath);
if (!basePathExists) Directory.CreateDirectory(basePath);
var fileName = Path.GetFileNameWithoutExtension(file.FileName);
var filePath = Path.Combine(basePath, file.FileName);
var extension = Path.GetExtension(file.FileName);
if (!File.Exists(filePath))
{
using (var stream = new FileStream(filePath, FileMode.Create))
{
await file.CopyToAsync(stream);
}
_fileModel = new FileModel
{
FileName = fileName,
FileType = file.ContentType,
FilePath = filePath
};
}
}
return _fileModel;
}
}
As u guys can see,its a different layer and there is nothing related with my Mvc project.
Im getting error when i add those extension to my Mvc project.
The error says me that :
'Some services are not able to be constructed (Error while validating the service descriptor
'ServiceType: CORE_HBKSOFTWARE.Interfaces.IFileUploader Lifetime: Singleton ImplementationType:
CORE_HBKSOFTWARE.Classes.FileUploader': Unable to resolve service for type
'CORE_HBKSOFTWARE.Models.FileModel' while attempting to activate
'CORE_HBKSOFTWARE.Classes.FileUploader'.)'
I dont know why im getting that error. That FileModel class is seems to okey to me and i still dont know. I allready add my services.AddSingleton<IFileUploader, FileUploader>(); to my Startup.cs .
Thanks for any suggestion !
If you want to use constructor injection to create an instance of FileModel in your FileUploader class you need to register it to the IoC Container. You do that by calling following method in the ConfigureServices method:
services.AddSingleton<FileModel>();
You can also choose a different lifetime by calling AddScoped or AddTransient.

Xamarin How to send a Post with my entrys

I need to fill a form with inputs in Xamarin, and send them to my API page.
I already tried sending the data in "Postman" and it saved it correctly, but I would like to know how to send it from Xamarin.
Attention, I can read the data correctly from the application.
public class FuelPurchase
{
public int id { get; set; }
public string date{ get; set; }
public int vueltametal { get; set; }
public int amount{ get; set; }
public string station{ get; set; }
public string location{ get; set; }
}
And the form you create in Xamarin is this.
<Label Text="Fuel Purchase"/>
<Label Text="Fecha">
<DatePicker x:Name="Date"/>
<Label Text="Station"/>
<Entry x:Name="Station"/>
<Label Text="Location"/>
<Entry x:Name="Location"/>
<Label Text="Amount"/>
<Entry x:Name="amount" Keyboard="Numeric"/>
Here is a static class that I use for API's. You can change the url to match yours if you only have one. Make sure to step through it and check that all of your "/"'s are in the right spot!
using Newtonsoft.Json;
using System;
using System.Diagnostics;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using NGJS = System.Text.Json;
using System.Threading.Tasks;
namespace TestBCS
{
public class RestService
{
readonly HttpClient client;
public RestService()
{
client = new HttpClient(new HttpClientHandler
{
Proxy = null,
UseProxy = false
});
}
#region GET
public async Task<object> RefreshDataAsync(string url, string qs)
{
Uri uri = new Uri(string.Format(url, qs));
HttpResponseMessage response = await client.GetAsync(uri);
if (response.IsSuccessStatusCode)
{
using (var stream = await response.Content.ReadAsStreamAsync())
{
return await NGJS.JsonSerializer.DeserializeAsync<object>(stream);
}
}
//Error Handling here
return null;
}
#endregion
#region POST
static void SerializeJsonIntoStream(object value, Stream stream)
{
using (var sw = new StreamWriter(stream, new UTF8Encoding(false), 1024, true))
using (var jtw = new JsonTextWriter(sw) { Formatting = Formatting.None })
{
var js = new JsonSerializer();
js.Serialize(jtw, value);
jtw.Flush();
}
}
HttpContent CreateHttpContent(object content)
{
HttpContent httpContent = null;
if (content != null)
{
var ms = new MemoryStream();
SerializeJsonIntoStream(content, ms);
ms.Seek(0, SeekOrigin.Begin);
httpContent = new StreamContent(ms);
httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
}
return httpContent;
}
public async Task PostStreamAsync(string url, object content)
{
string Url = url;
using (var client = new HttpClient())
using (var request = new HttpRequestMessage(HttpMethod.Post, Url))
using (var httpContent = CreateHttpContent(content))
{
request.Content = httpContent;
using (var response = await client
.SendAsync(request, HttpCompletionOption.ResponseHeadersRead)
.ConfigureAwait(false))
{
response.EnsureSuccessStatusCode();
Debug.WriteLine("Successfully Sent");
}
}
}
#endregion
}
}

Serialize the Data into JSON

Would like to make this solution as a generic solution wherein instead of Person object, GetJSON Method should accept the generic type which is has the DataContract attribute. Can anybody explain how to go about doing it.
Here is the base code
namespace TestDataContractJsonSerializer
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.IO;
using System.Runtime.Serialization.Json;
public class Program
{
public static void Main(string[] args)
{
List<Person> persons = new List<Person> { new Person("Person1"), new Person("Person2") };
var strJSON = from p in persons select GetJSON(p);
Console.WriteLine("In JSON Format: ");
foreach (string str in strJSON)
{
Console.WriteLine(" {0}", str);
}
Console.ReadKey();
}
private static string GetJSON(Person p)
{
if (p != null)
{
MemoryStream stream = new MemoryStream();
DataContractJsonSerializer dataContractJsonSerializer = new DataContractJsonSerializer(typeof(Person));
dataContractJsonSerializer.WriteObject(stream, p);
stream.Position = 0;
StreamReader sr = new StreamReader(stream);
return sr.ReadToEnd();
}
return string.Empty;
}
}
[DataContract]
public class Person
{
public Person(string name)
{
this.Name = name;
}
[DataMember]
public string Name { get; private set; }
}
}
It would look something like this in the very basic case. You'd probably need to add some special casing and/or error handling, for instance if the type T is not serializable.
private static string GetJSON<T>(T objToSerialize)
{
if (objToSerialize != null)
{
MemoryStream stream = new MemoryStream();
DataContractJsonSerializer dataContractJsonSerializer = new DataContractJsonSerializer(objToSerialize.GetType());
dataContractJsonSerializer.WriteObject(stream, objToSerialize);
stream.Position = 0;
StreamReader sr = new StreamReader(stream);
return sr.ReadToEnd();
}
return string.Empty;
}