You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@pdfbox.apache.org by "bal (JIRA)" <ji...@apache.org> on 2018/09/14 13:42:01 UTC

[jira] [Reopened] (PDFBOX-4312) byte array format to pass to sign method

     [ https://issues.apache.org/jira/browse/PDFBOX-4312?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

bal reopened PDFBOX-4312:
-------------------------

I am signing pdf using external *pkcs 7*  signature with pdfbox 1.8.9 in .net. I have set all signatureproperties.I have *converted the base64 encoded signature in pkcs7 format to byte array by casting the responsexml to object. The byte array size is 2911 and i am passing this byte array to sign method which is called through saveincremental method*.but when i open pdf it shows me signed by unknown . when i expand this it show me there are *errors in the formatting or information contained in the signature.* please find below my code what is wrong in code ?? thanks in advance.
{code:java}
protected void Page_Load(object sender, EventArgs e)
{

string elemString = "";
string pdfPath = @"D:\balasaheb\esign_file_demo\testing.pdf";
float xCo_ordinates = 150;
float yCo_ordinates = 400;
float signatureWidth = 250;
float signatureHeight = 100;
string nameToShowOnSignatureStamp = "Sushrut Sathe";
string locationToShowOnSignatureStamp = "Latur";
string reasonForSign = "Testing";
string pdfPassword = "";
string txn = "";
int log_err = 1;
int stampingPage = 1;

string pdfname = System.IO.Path.GetFileName(pdfPath);

string pdfDirectory = System.IO.Path.GetDirectoryName(pdfPath);
string pdf = System.IO.Path.GetFileNameWithoutExtension(pdfPath);

string outputFinalPdfDir = pdfDirectory;
//string responseXml = System.IO.File.ReadAllText(@"D:\balasaheb\esign_file_demo\testing_responseXML.txt");
string responseXml = System.IO.File.ReadAllText(@"D:\balasaheb\esign_file_demo\responsexml.txt");
// Response XML Digest 
//****************************************************************************************************
// string responseXml = Request["msg"].ToString();

XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(responseXml);

XmlNodeList elemList = xmlDoc.GetElementsByTagName("DocSignature");
XmlNodeList esignResp = xmlDoc.GetElementsByTagName("EsignResp");

//string responseDocText = "Responsexml.txt";

foreach (XmlElement elem in esignResp) // elemList)
{
// elemString = elem.InnerText;
string respStr = elem.OuterXml;
// using (StreamWriter sw = new StreamWriter(pdfDirectory + "\\" + responseDocText))
// {
// sw.Write(responseXml);
// sw.Close();
// }
//}

// signature to byte array conversion
byte[] signatureByte = Convert.FromBase64String(elemString);

//byte sigarr = Convert.ToByte(elemString);

// byte[] bytes = Encoding.UTF8.GetBytes(elemString);
// byte[] sigarr = integersToBytes(signatureByte);

byte[] sigbyts = System.Text.Encoding.UTF8.GetBytes(elemString);

//using java conversion method

byte[] bytes = Base64.encode(elemString.getBytes());

byte[] name = Base64.encode(elemString.getBytes());

byte[] decodedString = elemString.getBytes("UTF-8");

string docStr = Convert.ToBase64String(signatureByte);
// conversion ascii
byte[] asciiBytes = Encoding.ASCII.GetBytes(docStr);

//decode and convert to byte array
byte[] docBytes = Convert.FromBase64String(elemString);

//string DocStr = Encoding.UTF8.GetString(docBytes);

//byte[] docbytes = Encoding.UTF8.GetBytes(DocStr);

// string docSig = Convert.ToBase64String(docBytes);

EsignResponse resp = new EsignResponse();
// resp.getClass();

XmlObjectConverter xmlobj = new XmlObjectConverter();
EsignResponse fg = (EsignResponse)xmlobj.XmlToObject(resp, responseXml);

byte[] docsig = fg.Signatures.DocSignature.docBytes;

// string str = System.Text.ASCIIEncoding.ASCII.GetString(docsig);
//store sigbytes to dictionary
docSigDict.Add("doc", docsig);

java.io.File inPutPdf = new java.io.File(pdfPath);

string inPutPdfName = inPutPdf.getName();

FileInputStream fis = new FileInputStream(inPutPdf);
// byte[] byteArray = null;

InputStream inputStream = new FileInputStream(inPutPdf);

System.String inputStreamToString = inputStream.toString();

inputStream.close();

//java.io.File outPutPdf = new java.io.File(pdfDirectory + "\\" + pdf + "Signed_Final.pdf");
//FileOutputStream fos = new FileOutputStream(outPutPdf);

//org.apache.pdfbox.io.IOUtils.copy(fis, fos);
//fis.close();


PDDocument signedDoc = PDDocument.load(pdfDirectory + "\\" + "testing.pdf");
signedDoc.getDocument().getTrailer().removeItem(COSName.TYPE);

int pages = signedDoc.getNumberOfPages();

string tickImagePath = @"D:\balasaheb\tick.jpg";

FileInputStream tickImageStream = new FileInputStream(tickImagePath);


List<Long> documentIds = new List<Long>();

List<string> calTimeStamp = new List<string>();

BoundingBox box = new BoundingBox();

PDRectangle Rect = new PDRectangle(box);

java.util.Calendar cal = java.util.GregorianCalendar.getInstance();
SimpleDateFormat sd = new SimpleDateFormat("yyyyMMdd_HHmmss");
string timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(java.util.Calendar.getInstance().getTime());
cal.setTime(sd.parse(timeStamp));
cal.add(java.util.Calendar.MINUTE, 15);

System.Random random = new System.Random();

int mapId = 0;

Long docid = new Long(mapId + random.Next(1000, 9980));

string docIdTxt = pdfDirectory + "\\DocumentId.txt";

using (var streamReader = new StreamReader(pdfDirectory + "\\" + "timeStamp.txt", Encoding.UTF8))
{
timeStamp = streamReader.ReadToEnd();
}

int id;
using (TextReader reader = System.IO.File.OpenText(docIdTxt))
{
id = int.Parse(reader.ReadLine());
}


Hash hash1 = new Hash();
string outpdfpath = pdfDirectory + "\\" + pdf + ".pdf";
string pdfUnsignedHash = hash1.CalHash(outpdfpath);
string unsignedHash = "pdfHash1.txt";

using (StreamWriter sw = new StreamWriter(pdfDirectory + "\\" + unsignedHash))
{
sw.Write(pdfUnsignedHash);
sw.Close();
}

try
{
// create visible signature properties
PDVisibleSigProperties signatureProperties = new PDVisibleSigProperties();

//represents a digital signature that can be attached to a document.
org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature pdsignature = new org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature();
pdsignature.setFilter(org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature.FILTER_ADOBE_PPKLITE);
pdsignature.setSubFilter(org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);

//create signature dictionary
//pdsignature.setLocation(locationToShowOnSignatureStamp);
//pdsignature.setReason(reasonForSign);
//pdsignature.setSignDate(cal);
//pdsignature.getLocation();
//pdsignature.getName();
signedDoc.setDocumentId(docid);
calTimeStamp.Add(timeStamp);

//build visible signature template to add in pdf
PDVisibleSigBuilder signatureBuilder = new PDVisibleSigBuilder();

// create pdftemplate
PDFTemplateCreator tempCreator = new PDFTemplateCreator(signatureBuilder);

signatureBuilder.createAcroForm(signedDoc);
//build visible signature design
PDVisibleSignDesigner visibleSigDesign = new PDVisibleSignDesigner(signedDoc, tickImageStream, 1);
visibleSigDesign.xAxis(xCo_ordinates);
visibleSigDesign.yAxis(yCo_ordinates).zoom(10);
visibleSigDesign.signatureFieldName("signature");
signatureProperties.signerName("name").signerLocation("location")
.signatureReason("Security")
//Sets the preferred signature size in bytes.
.preferredSize(5).page(1)
// set visual signature add or not
.visualSignEnabled(true)
//set visible signature config obj and returns visible sig properties
.setPdVisibleSignature(visibleSigDesign)
//start building of visible signature
.buildSignature();

//create default signature options.
SignatureOptions sigOptions = new SignatureOptions();

if (signatureProperties != null && signatureProperties.isVisualSignEnabled())
{
sigOptions.setPage(signatureProperties.getPage());

//read visual signature from signature properties
sigOptions.setVisualSignature(signatureProperties);

//sigOptions.setVisualSignature(createVisualSignatureTemplate(signedDoc, stampingPage, tickImagePath, nameToShowOnSignatureStamp,locationToShowOnSignatureStamp
// , reasonForSign));

// add signature to document
signedDoc.addSignature(pdsignature, this, sigOptions);

}
else
{
signedDoc.addSignature(pdsignature, this);
}
}
catch (System.Exception ex)
{
ex.Message.ToString();
}


// Get the first page
PDDocumentCatalog catalog = signedDoc.getDocumentCatalog();

int pageCount = 1;


string hash2 = hash1.CalHash(outpdfpath);
string hash2txt = "pdfhash2.txt";

using (StreamWriter sw = new StreamWriter(pdfDirectory + "\\" + hash2txt))
{
sw.Write(hash2);
sw.Close();
}

try
{
//InputStream fis = new FileInputStream(pdfDirectory + "\\" + "testingField.pdf");

////remove unwanted trailer entry in pdfdoc
//byte[] inputBytes = IOUtils.toByteArray(fis);
//PDDocument pdDocument = PDDocument.load(new ByteArrayInputStream(inputBytes));
//PDJpeg ximage = new PDJpeg(pdDocument, tickImageStream);
//PDPage page = (PDPage)pdDocument.getDocumentCatalog().getAllPages().get(0);
//PDPageContentStream contentStream = new PDPageContentStream(pdDocument, page, true, true);
//contentStream.drawXObject(ximage, 50, 50, 356, 40);
//contentStream.close();
////Creates a new byte array output stream.
//ByteArrayOutputStream os = new ByteArrayOutputStream();
//pdDocument.save(os);
//os.flush();

// remove unwanted trailer from trailer dictionary and set cross reference same for incremental update
//ByteArrayOutputStream baos = new ByteArrayOutputStream();
//signedDoc.save(baos);
//baos.flush();
//signedDoc.close();

//byte[] inputBytes = baos.toByteArray();
//signedDoc = PDDocument.load(new ByteArrayInputStream(inputBytes));
//signedDoc.getDocument().getTrailer().removeItem(COSName.TYPE);
PDPage page = new PDPage();

signedDoc.getDocumentCatalog().getCOSObject().setNeedToBeUpdate(true);
signedDoc.getDocumentCatalog().getPages().getCOSObject().setNeedToBeUpdate(true);
//page.getCOSObject().setNeedToBeUpdate(true);
//page.getResources().getCOSObject().setNeedToBeUpdate(true);
//page.getResources().getCOSDictionary().getDictionaryObject(COSName.XOBJECT).setNeedToBeUpdate(true);
////ximage.getCOSObject().setNeedToBeUpdate(true);


Debug.WriteLine("calling saveincremental");
signedDoc.saveIncremental(pdfDirectory + "\\" + pdf + "Signed_Final.pdf");
signedDoc.close();

}
catch (System.Exception ex)
{
ex.Message.ToString();

}

}
}

private byte[] integersToBytes(byte[] signatureByte)
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
for (int i = 0; i < signatureByte.Length; ++i)
{
dos.writeInt(signatureByte[i]);
}

return baos.toByteArray();
}

private InputStream createVisualSignatureTemplate(PDDocument signedDoc, int stampingPage, string tickImagePath, string nameToShowOnSignatureStamp, string locationToShowOnSignatureStamp, string reasonForSign)
{

java.io.File imageFile = new java.io.File(tickImagePath);

COSDictionary cosDict = new COSDictionary();

PDPage page = new PDPage(cosDict);

signedDoc.addPage(page);

List<PDSignatureField> acroFormFields = new List<PDSignatureField>();

try
{
//
PDAcroForm acroForm = new PDAcroForm(signedDoc);
signedDoc.getDocumentCatalog().setAcroForm(acroForm);

PDSignatureField signatureField = new PDSignatureField(acroForm);
PDAnnotationWidget widget = new PDAnnotationWidget();
acroForm.getCOSObject().setDirect(true);
acroFormFields.Add(signatureField);

PDStream pdstream = new PDStream(signedDoc);

//PDFormXObject form = new PDFormXObject(pdstream);

PDResources res = new PDResources();
PDFont font = PDType1Font.HELVETICA_BOLD;
PDResources rest = new PDResources();
//form.setResources(rest);
//form.setFormType(1);
//PDRectangle bbox = new PDRectangle(rect.getWidth(), rect.getHeight());
//float height = bbox.getHeight();

// form.PDVisualSigBuilder.createAppearanceDictionary();
PDAppearanceDictionary appearanceDict = new PDAppearanceDictionary();
appearanceDict.getCOSObject().setDirect(true);
RandomAccess random = null;
COSStream str = new COSStream(cosDict, random);
PDAppearanceStream appearanceStream = new PDAppearanceStream(str);
appearanceDict.setNormalAppearance(appearanceStream);
widget.setAppearance(appearanceDict);

try
{
PDPage page1 = new PDPage();
PDPageContentStream contentStream = new PDPageContentStream(signedDoc, page1);
//cs.setNonStrokingColor(java.awt.Color.black);
contentStream.addRect(-5000, -5000, 2000, 2000);
contentStream.fill(1);
contentStream.saveGraphicsState();
PDJpeg tickjpg = new PDJpeg(pdstream);

contentStream.drawImage(tickjpg, 0, 0);
contentStream.restoreGraphicsState();
//show text 

PDFont font1 = PDType1Font.TIMES_ITALIC;
float fontSize = 8;
float leading = fontSize * 1.0f;
contentStream.beginText();
contentStream.setFont(font, fontSize);

ByteArrayOutputStream baos = new ByteArrayOutputStream();
signedDoc.save(baos);
}
catch (System.Exception e)
{
e.ToString();
}
}
catch (System.Exception ex)
{
ex.ToString();
}

return null;
}


// 
public byte[] sign(InputStream @is)
{
InputStream ipstream = @is;

byte[] pdf = null;

try
{
FileOutputStream fos = new FileOutputStream(@"D:\balasaheb\esign_file_demo" + "\\" + "temp_Signed.pdf");

byte[] buffer = new byte[ipstream.available()];
fos.write(buffer);
fos.flush();
fos.close();
ipstream.close();

pdf = docSigDict["doc"];

}
catch (System.Exception e)
{
e.ToString();
}

return pdf;
}

private string gethash(string newPdfPath)
{
java.nio.file.Path pdfPath = Paths.get(newPdfPath);
byte[] pdfbytes = Files.readAllBytes(pdfPath);

SHA256 sha256 = SHA256.Create();
byte[] hash = sha256.ComputeHash(pdfbytes);

java.lang.StringBuilder sb = new java.lang.StringBuilder();
for (int i = 0; i < hash.Length; i++)
{
sb.append(hash[i].ToString("X2"));
}
return sb.ToString();

}
{code}

> byte array format to pass to sign method
> ----------------------------------------
>
>                 Key: PDFBOX-4312
>                 URL: https://issues.apache.org/jira/browse/PDFBOX-4312
>             Project: PDFBox
>          Issue Type: Wish
>          Components: .NET, PDModel, Signing
>    Affects Versions: 1.8.9
>            Reporter: bal
>            Priority: Critical
>
> Hi ,
> I want to sign pdf using signature in pkcs 7 format . I am converting pkcs 7 signature to byte array using Convert.FromBase64String method in .net . I am passing this byte array to sign method in signature interface which gets called after calling saveincremental. My byte array is inserting proper but the name of which signature is not shown when i open pdf. May be my byte conversion may not proper or something else i am doing wrong. please let me know.



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@pdfbox.apache.org
For additional commands, e-mail: dev-help@pdfbox.apache.org