PKI Signering
Her finner du dokumentasjon på hva en IPS signering er og fungerer, hvordan du bygger opp en signerings forespørselen og tolker responsen. Du finner også informasjon om de forskjellige signeringsformatene som er støttet, hvordan dette brukes og hvordan man trygt kan overføre dokumentet til klientsiden.
Merk at
eksempelkodene i denne siden er kun ment som illustrasjonseksempeler på kjernemekanismene, og bør "robustifieres"/justeres med feilhåndtering og/eller andre nødvendige tilpasninger før en ev. produksjonssetting.
Hva er en IPS signering?
En signering gjennom IPS gir en sluttbruker mulighet for å se på og signere et dokument med sin PKI. Dokumentet tilgjengeliggjøres på brukerstedets server, og lastes ned til klienten. På klienten kan sluttbrukeren se på dokumentet gjennom sin installerte "viewer" for det aktuelle dokumentformatet før det signeres. Når dokumentet er signert, vil IPS verifisere signaturen, og returnere signatur og sertifikat tilbake til brukerstedet. På brukerstedssiden vil brukerstedet kunne sette sammen den angitte SDO typen basert på disse elementene, og verifisere signaturen/SDO'en om ønskelig. Signaturformatene støttes gjennom en SignatureProvider plugin arkitektur. Etter hvert som det tilkommer støtte for flere signaturformater, kan disse lastes ned fra disse sidene. Man kan også implementere egne plugins hvis ønskelig, men kravet til input data til eventuelle egenutviklede plugins må samsvare med en av de eksisterende SignatureProvider plugin'ene.
Hvordan er prinsippene ift What-you-see-is-what-you-sign implementert i IPS ?
For å kunne sannsynliggjøre at det du ser er det du signerer (WYSIWYS-prinsippet), er det viktig å ha en så nære knyttning som mulig mellom "se-på prosessen" og signeringsprosessen. Helst bør dette skje i en egen ekstern "signerings-terminal" som er lukket og beskyttet fra PC'en ellers. Allikevel må man ha tilitt til denne signerings-terminalen, og det får man gjerne gjennom dokumentasjon, sertifiseringer og andre bekreftelser fra anerkjente leverandører.
For å kunne tilby en signeringsløsning på Internet uten en slik "signerings-terminal", er det viktig at de som bruker signeringsløsningen og de som tilbyr signering gjennom en slik løsning, kjenner til hvordan man i størst mulig grad sannsynliggjør at det du faktisk ser er det du faktisk signerer. Derfor er det viktig at denne informasjonen er tilgjengelig, og at man da selv kan ta stilling til om man syntes disse mekanismene sannsynliggjør dette i tilstrekkelig grad.
I IPS er dette sannsynliggjort ved at dokumentet lastes ned på klienten, og inn i samme prosess som skal styre den faktiske signeringen mot Smartkortet. Dataene fra samme prosess tilgjengeliggjøres for visning, sammen med mime-typen brukerstedet selv har angitt for innholdet (f.eks. "application/pdf"). På denne måten startes så det aktuelle programmet sluttbrukeren har installert for den gitte mime-typen (f.eks. Adobe Reader), og dokumentet vises i dette programmet. Når sluttbrukeren har sett på dokumentet/filen som skal signeres, taster brukeren PIN-kode, og korrekt preprosessert DTBS (Data-To-Be-Signed) i forhold til angitt signaturformat over de samme dataene signeres.
SignatureProvider plugin
Signaturformatsøttten i integrasjonsbibliotekene er implementert gjennom en såkalt SignatureProvider plugin arkitektur. En SignatureProvider plugin tilbyr encoding og verifisering av sine relevante formater og delstrukturer. F.eks. vil BPESIG0101 plugin, som støtter basic PKCS#7 SDO'er, tilby støtte for encoding av alle relevante delstrukturer som brukes i en basic PKCS#7 signering. Det samme gjelder for de andre signaturformatene.
SignatureProvider kode pattern for SDO generering vil være slik:
Code Block |
---|
// get the correct provider instance
SignatureProvider sp = SignatureProvider.getInstance([format]);
sp.initializeForEncode([encoding mode]);
// add all required parameters
sp.setParam([dataparam name-1],[value-1]);
..
sp.setParam([dataparam name-n],[value-n]);
// encode the given structure
byte[] encodedData = sp.encode(); |
SignatureProvider kode pattern for SDO verifisering vil være slik:
Code Block |
---|
// get the correct provider instance
SignatureProvider sp = SignatureProvider.getInstance([format]);
sp.initializeForVerify([verification mode]);
// add all required parameters
sp.setParam([dataparam name-1],[value-1]);
..
sp.setParam([dataparam name-n],[value-n]);
// verify the given structure
boolean verifiedOk = sp.verify(); |
Under følger en global liste over alle dataparameter typer.
Følgende dataparametere er felles for alle BPESIG SignatureProvider plugins
Parameter | Type | Beskrivelse |
---|---|---|
DTBS | byte[] | Data-To-Be-Signed - dette er de faktiske binære dataene som signeres etter all nødvendig preprosessering, uten padding. |
CONTENT | byte[] | Eksakt binær representasjon av dokumentet/filen som skal signeres. |
CONTENT_SHA1_DIGEST | byte[] | Hash av CONTENT i henhold til spesifisert hash-algoritme |
CMS_SIGNED_ATTRIBUTES | byte[] | CMS SignedAttributes. Den binære representasjonen av en PKCS#7 v1.5 SignedAttributes som skal brukes ved signering/verifisering. |
CLAIMED_SIGNING_TIME | Date (Java)/ | Datoobjekt som representerer brukerstedets oppfatning av tidspunkt for signering. |
CERTIFICATE | byte[] | Binær representasjon av X509 Sertifikatet som skal brukes ved signering. |
SIGNATURE | byte[] | Binør representasjon av signaturen. For en 1024 bits RSA signering vil denne eksempelvis være 128 bytes lang. |
CMS_SIGNED_DATA_OBJECT | byte[] | CMS SignedDataObject. Den binære representasjon av en PKCS#7 v1.5 SignedDataObject som skal brukes ved signering/verifisering. |
SEID_INCLUDE_SIGNEDOBJECT | String ("1"/"0") | 1 hvis CONTENT skal være med i SEID_SDO'en, 0 hvis ikke |
SEID_INCLUDE_HASHEDDATA | String ("1"/"0") | 1 hvis HashedData elementet skal være med i SEID_SDO'en, 0 hvis ikke |
PDF_SIGNED | ||
SIGNATURE_CONTEXT | cnl.wips.remote.tools.crypto.SignatureContext | Tilstandsholder objekt gjennom de forskjellige fasene av encoding. Et tomt SignatureContext objekt opprettes gjennom å kalle SignatureProvider.createSignatureContext() på den aktuelle SignatureProvideren |
VISIBLE_SIGNATURE_PAGE | String | Side nummer som den synlige signaturen skal ligge på |
VISIBLE_SIGNATURE_X | String | Den horisontale posisjonen til den synlige signaturen |
VISIBLE_SIGNATURE_Y | String | Den vertikale posisjonen til den synlige signaturen |
VISIBLE_SIGNATURE_WIDTH | String | Bredden til den synlige signaturen |
VISIBLE_SIGNATURE_HEIGHT | String | Høyden til den synlige signaturen |
REASON | String | Tekstlig beskrivelse av grunn/årsak til at signaturen lages. |
SIGNED_LOCATION | String | Tekstlig beskrivelse av signeringssted. |
Under følger en global liste over alle encoding modes
Følgende encoding mode identifikatorere er felles for alle BPESIG SignatureProvider plugins
Parameter | Beskrivelse |
---|---|
DTBS | Data-To-Be-Signed - genererer de faktiske binære dataene som signeres etter all nødvendig preprosessering, uten padding. |
CMS_SIGNED_ATTRIBUTES | CMS SignedAttributes. Genererer den binære represenatsjonen av en PKCS#7 v1.5 SignedAttributes som skal brukes ved signering. |
CMS_SIGNED_DATA_OBJECT | CMS SignedDataObject. Genererer den binære represenatsjonen av en PKCS#7 v1.5 SignedDataObject som skal brukes ved signering. |
SEID_SDO_BASIC | Genererer den binære representasjonen av en SEID_SDO_Basic XML struktur. |
PDF_SIGNED | Genererer den signerte PDF'en. |
Under følger en global liste over alle verification modes
Følgende verification mode identifikatorere er felles for alle BPESIG SignatureProvider plugins
Parameter | Beskrivelse |
---|---|
CMS_SIGNED_DATA_OBJECT_INTEGRITY | Verifiserer signatur objektets integritet. Dvs at strukturen i seg selv blir verifisert; signatur mot innhold og innhold i signed attributes, integretet og levetid på sertifikat, men ingen revokeringssjekk. |
SEID_SDO_BASIC_CMS_INTEGRITY | Verifiserer det interne CMS signatur objektets integritet i SEID_SDO'en. Dvs at den interne CMS strukturen i seg selv blir verifisert; signatur mot innhold og innhold i signed attributes, integretet og levetid på sertifikat, men ingen revokeringssjekk. |
PDF_SIGNED | Verifiserer det interne PDF dokumentet opp mot signaturen, integretet og levetid på sertifikat, men ingen revokeringssjekk eller sjekk mot CA sertifikat. |
Signaturformater
Følgende signatur formater støttes av IPS:
Verdi | Fra versjon | Beskrivelse |
---|---|---|
BPESIG0101 | 1.0.1 | CMS basert signatur basert på PKCS#7, v1.5. Gir mulighet for å inkludere claimed signing-time i signatur grunnlaget (signed-attributes) |
BPESIG0201 | 1.0.1 | CMS basert signatur basert på ETSI 101 733 v1.7.3. Dataene signeres og formateres iht CAdES-BES formatert signaturer. Gir mulighet for å inkludere claimed signing-time i signatur grunnlaget. |
BPESIG0301 | 1.0.1 | CMS og XML basert signatur. Dataene signeres og formateres iht SEID SDO Basic (Type 1) profilen. |
BPESIG0401 | 1.0.3 | Adobe PDF signatur, usynlig signatur. |
BPESIG0402 | 1.0.3 | Adobe PDF signatur, visuelt synlig signatur i dokumentet |
Du finner mer informasjon om de ulike signaturformatene lenger ned.
Dokumentformater
IPS har ikke noe teknisk forhold til formatet på dokumentet utover mime-typen som anngis for det for det aktuelle formatet av brukerstedet selv. Dette betyr at man i prinsippet står fritt til å signere alle type dokumenter/filer, fra PDF'er og Word dokumenter til .exe filer og .zip filer. "Viewer" prosessen blir da håndtert slik den aktuelle applikasjonen for den gitte mime-typen håndterer det. Av sikkerhetsmessige årsaker har Buypass begrenset IPS til å kun signere PDF (application/pdf) og rene tekstfiler (text/plain). Hvis det er behov for å kunne signere andre type formater, kontakt Buypass for videre diskusjon.
Nedlasting av dokumenter til sluttbruker
Som tidligere nevnt, lastes det aktuelle dokumentet over til kundens PC i forkant av selve signeringen. Det finnes det flere varianter å tilgjengeliggjøre dokumentet på. Dokumentet må på en eller annen måte tilgjengeliggjøres for signeringsappleten, slik at denne kan lastes ned for visning- og signering. Det finnes følgende alternativer for tilgjengeliggjøring:
Tilgjengeliggjøre dokumentet på åpen, ikke-gjettbar/uforutsigbar, URL
Tilgjengeliggjøre dokumentet på en sesjonsbasert URL. Sesjonscookien sendes da med i forespørselen til IPS
Tilgjengeliggjøre en kryptert (3DES/168bit) utgave dokumentet på en åpen eller sesjonsbasert URL. Dekrypteringsnøkkelen (og ev. sesjonscookien) sendes da med i forespørselen til IPS. WIRI tilbyr støttefunksjonalitet for kryptering, nøkkelgenering og base64 encoding av dokumenter som tilgjengeliggjøres på denne måten.
Sende dokumentet med i forespørselen til IPS. Dette anbefales kun for små dokumenter. Total maks størrelse på en forespørsel til IPS er 256kb, men det anbefales uansett ikke å sende større dokumenter enn 3-5kb via IPS, da dokumentet må lastes opp (x1) og ned (x2) 3 ganger før det er "fremme" hos sluttbrukeren.
Hvis dokumentet tilgjengeliggjøres på Internet, bør dokumentet tilgjengeliggjøres på en SSL adresse. Alternativt krypteres som i alternativ 3), og tilgjengeliggjøres over http.
SignaturFormat BPESIG0101 - PKCS#7 v1.5 SDO
BPESIG0101 som signaturformat er basert på PKCS#7 v1.5 / RFC 2315. Utover det som er påkrevd, inkluderes også såkalt Claimed Signing Time som i dette tilfellet er brukerstedets oppfatning av signeringstidspunktet.
Tabellen under viser hvilke felter som er påkrevd for de forskjellige relevante operasjonene for BPESIG0101 SignatureProvider. Se kapittelet
om SignatureProvider
for detaljert beskrivelse av hva de forskjellige parameterne betyr.
Modus | Encoding/Verification name | Påkrevde Felter | Overordnet beskrivelse |
---|---|---|---|
Encoding | CMS_SIGNED_DATA_OBJECT | CONTENT | Genrerer hele PKCS#7 SDO'en |
Verifisering | CMS_SIGNED_DATA_OBJECT_INTEGRITY | CMS_SIGNED_DATA_OBJECT | Verifiserer integriteten i PKCS#7 SDO'en (ingen revokeringssjekk) |
Under er et kodeeksempel på sammensetting av en PKCS#7. Eksempelet er basert på at man har fått tilbake signatur og sertifikat etter signering, og at man har det signerte dokumentet og signeringstidspunkt tilgjengelig.
Code Block |
---|
byte[] document = // the document
byte[] signature = // the signature
byte[] certificate = // the encoded certificate
Date signingTime = // the given signingTime
// get the BPESIG0101 signature provider
SignatureProvider sp = SignatureProvider.getInstance("BPESIG0101");
// initialize for encoding of the PKCS#7 signature SDO
sp.initializeForEncode("CMS_SIGNED_DATA_OBJECT");
// add required parameters
sp.setParam("CONTENT", document); // the excact binary representation
sp.setParam("CLAIMED_SIGNING_TIME", signingTime); // same as the SigningTime sent to IPS
sp.setParam("CERTIFICATE", certificate); // certificate from IPS
sp.setParam("SIGNATURE", signature); // signature from IPS
// get the encoded PKCS#7 signature SDO
byte[] pkcs7 = sp.encode();
Under er et kodeeksempel på verifisering av et signert dokument (verifisering av PKCS#7'en).
byte[] pkcs7 = // the signature, or from previous sample
// get the BPESIG0101 signature provider
SignatureProvider sp = SignatureProvider.getInstance("BPESIG0101");
// initialize for signature verification of the PKCS#7 signature SDO
sp.initializeForVerify("CMS_SIGNED_DATA_OBJECT_INTEGRITY");
// add required parameters (the signature)
sp.setParam("CMS_SIGNED_DATA_OBJECT", pkcs7);
// verify SDO integrity
boolean verifiedOk = sp.verify(); |
SignaturFormat BPESIG0201 - ETSI TS 101 733 CAdES-BES SDO
BPESIG0201 som signaturformat er basert på PKCS#7 v1.5 / RFC 2315, men inkluderer i tillegg påkrevde elementer for å være konform
med ETSI TS 101 733
CAdES-BES. Tilleggs elementene er hentet
fra ESS RFC263 (Enhanced Security Servies), og består
av signing-certificate
elementet eller other-signing-certificate
. IPS
inkluderer signing-certificate
elementet, som kort fortalt består av en SHA-1 Hash over signerers sertifikat. Dette inkluderes i signaturgrunnlaget for å sikre en entydig knytning mellom signatur og et faktiske sertifikatet som ble brukt. Utover det som er påkrevd, inkluderes også Claimed Signing Time som i dette tilfellet er brukerstedets oppfatning av signeringstidspunktet.
Tabellen under viser hvilke felter som er påkrevd for de forskjellige relevante operasjonene for BPESIG0201 SignatureProvider. Se kapittelet
om SignatureProvider
for detaljert beskrivelse av hva de forskjellige parameterne betyr.
Modus | Encoding/Verification name | Påkrevde Felter | Overordnet beskrivelse |
---|---|---|---|
Encoding | CMS_SIGNED_DATA_OBJECT | CONTENT | Genrerer hele CAdES-BES SDO'en |
Verifisering | CMS_SIGNED_DATA_OBJECT_INTEGRITY | CMS_SIGNED_DATA_OBJECT | Verifiserer integriteten i CAdES-BES SDO'en (ingen revokeringssjekk) |
Under er et kodeeksempel på sammensetting av en CAdES-BES SDO. Eksempelet er basert på at man har fått tilbake signatur og sertifikat etter signering, og at man har det signerte dokumentet og signeringstidspunkt tilgjengelig.
Code Block |
---|
byte[] document = // the document
byte[] signature = // the signature
byte[] certificate = // the encoded certificate
Date signingTime = // the given signingTime
// get the BPESIG0201 signature provider
SignatureProvider sp = SignatureProvider.getInstance("BPESIG0201");
// initialize for encoding of the CAdES-BES signature SDO
sp.initializeForEncode("CMS_SIGNED_DATA_OBJECT");
// add required parameters
sp.setParam("CONTENT", document); // the excact binary representation
sp.setParam("CLAIMED_SIGNING_TIME", signingTime); // same as the SigningTime sent to IPS
sp.setParam("CERTIFICATE", certificate); // certificate from IPS
sp.setParam("SIGNATURE", signature); // signature from IPS
// get the encoded CAdES-BES SDO
byte[] pkcs7 = sp.encode(); |
Under er et kodeeksempel på verifisering av et signert dokument (verifisering av CAdES-BES SDO'en).
Code Block |
---|
byte[] pkcs7 = // the signature, or from previous sample
// get the BPESIG0201 signature provider
SignatureProvider sp = SignatureProvider.getInstance("BPESIG0201");
// initialize for signature verification of the CAdES-BES signature SDO
sp.initializeForVerify("CMS_SIGNED_DATA_OBJECT_INTEGRITY");
// add required parameters (the signature)
sp.setParam("CMS_SIGNED_DATA_OBJECT", pkcs7);
// verify SDO integrity
boolean verifiedOk = sp.verify(); |
SignaturFormat BPESIG0301 - SEID-SDO-Basic
BPESIG0301 som signaturformat er basert
med ETSI TS 101 733
CAdES-BES - som er påkrevd i SEID standarden. Tilleggs elementene er hentet
fra ESS RFC263 (Enhanced Security Servies), og består
av signing-certificate
elementet eller other-signing-certificate
. IPS
inkluderer signing-certificate
elementet, som kort fortalt består av en SHA-1 Hash over signerers sertifikat. Dette inkluderes i signaturgrunnlaget for å sikre en entydig knytning mellom signatur og et faktiske sertifikatet som ble brukt. Utover det som er påkrevd, inkluderes også Claimed Signing Time som i dette tilfellet er brukerstedets oppfatning av signeringstidspunktet.
SEID spesifiserer flere sett med profiler. BPESIG0301 er i.h.t. SEID-SDO-Basic profilen.
Tabellen under viser hvilke felter som er påkrevd for de forskjellige relevante operasjonene for BPESIG0301 SignatureProvider. Se kapittelet
om SignatureProvider
for detaljert beskrivelse av hva de forskjellige parameterne betyr.
Modus | Encoding/Verification name | Påkrevde Felter | Overordnet beskrivelse |
---|---|---|---|
Encoding | SEID_SDO_BASIC | CONTENT | Genrerer hele SEID SDO'en (XML) |
Verifisering | SEID_SDO_BASIC_CMS_INTEGRITY | SEID_SDO_BASIC | Verifiserer integriteten i CMS delen av SDO'en (ingen revokeringssjekk) |
Under er et kodeeksempel på sammensetting av en SEID SDO. Eksempelet er basert på at man har fått tilbake signatur og sertifikat etter signering, og at man har det signerte dokumentet og signeringstidspunkt tilgjengelig.
Code Block |
---|
byte[] document = // the document
byte[] signature = // the signature
byte[] certificate = // the encoded certificate
Date signingTime = // the given signingTime
// get the BPESIG0301 signature provider
SignatureProvider sp = SignatureProvider.getInstance("BPESIG0301");
// initialize for encoding of the SEID SDO
sp.initializeForEncode("SEID_SDO_BASIC");
// add required parameters
sp.setParam("CONTENT", document); // the excact binary representation
sp.setParam("CLAIMED_SIGNING_TIME", signingTime); // same as the SigningTime sent to IPS
sp.setParam("CERTIFICATE", certificate); // certificate from IPS
sp.setParam("SIGNATURE", signature); // signature from IPS
sp.setParam("MIME_TYPE", "application/pdf"); // the content is a PDF document
sp.setParam("MERCHANT_DESC", "Same description as shown in the IPS GUI");
sp.setParam("CHARACTER_ENCODING", "UTF-8"); // we want UTF-8 XML encoding
sp.setParam("SEID_INCLUDE_HASHEDDATA","1"); // we want to include the HashedData element
sp.setParam("SEID_INCLUDE_SIGNEDOBJECT","0"); // we dont want to include the doc
// get the encoded SEID SDO
byte[] seidSDO = sp.encode();
// seidSDO is the SEID-SDO XML - convert it to a string, for joy
String theXML = new String(seidSDO, "UTF-8");
Under er et kodeeksempel på verifisering av et signert dokument (verifisering av CMS delen av SEID SDO'en).
byte[] seidSDO = // the signature, or from previous sample
// get the BPESIG0301 signature provider
SignatureProvider sp = SignatureProvider.getInstance("BPESIG0301");
// initialize for signature verification of the CMS part of the SDO
sp.initializeForVerify("SEID_SDO_BASIC_CMS_INTEGRITY");
// add required parameters (the signature/SDO)
sp.setParam("SEID_SDO_BASIC", seidSDO);
// verify SDO integrity
boolean verifiedOk = sp.verify(); |
SignaturFormat BPESIG0401 - PDF signatur, usynlig signatur
BPESIG0401 som signaturformat er basert på Adobes PDF signeringsformat. Signaturene som er opprettet ved hjelp av BPESIG0401 er ikke synlige i dokumentet ved f.eks. print, men sjekkes/verifiseres gjennom en PDF viewer (som Adobe Reader).
SignaturFormat BPESIG0402 - PDF signatur, synlig signatur
BPESIG0402 som signaturformat er basert på Adobes PDF signeringsformat. Signaturene som er opprettet ved hjelp av BPESIG0402 er synlige i dokumentet ved f.eks. print, og kan sjekkes/verifiseres gjennom en PDF viewer (som Adobe Reader).
Sammensetting av forespørselen
Sammensetting av signeringsforespørselen skjer typisk når en sluttbruker ønsker å signere noe. Ved sammensetting av en signeringsforespørsel, er det flere ting man må ta stilling til:
Hvordan skal dokumentet tilgjengeliggjøres for sluttbrukeren?
Påstått signeringstidspunkt
Signaturformat
Dokumentformat/MIME-type
Hvilke returverdier du ønsker om sluttbrukeren
Hvilket brukergrensesnitt du ønsker å bruke
Retur URL (ved redirigerte forespørseler)
Pr des-08 er det kun Smartkort med PKI som kan brukes til signering.
Påstått signeringstidspunkt anngis
gjennom MerchantSigningTime
elementet.
Brukergrensesnitt kode anngis
gjennom RequestAttribute
elementet.
Retur URL anngis
i ResponseUrl
elementet.
Returverdier anngis
gjennom ResponseAttribute
elementet. Data om brukeren blir returnert gjennom IdToken elementet i responsen.
Støttebiblioteket vil hjelpe deg med de resterende påkrevde elementene.
Under er et JSP eksempel på en komplett sammensatt forespørsel, hvor vi tilgjengeliggjør dokumentet på en sesjonsbasert URL, kryptert. Nøkkelen og sesjonscookien utveksels i forespørselen til IPS, slik at innholdet i praksis kun kan leses av IPS klienten. Vi ønsker å få fødselsnummeret i retur, og vi ønsker også å bruke et "FULLSIZE" brukergrensesnitt, og må derfor anngi dette gjennom RequestAttribute elementet. Dokumentet er et PDF dokument, og vi bruker derfor mime-typen "application/pdf". Eksempelet under spesifiserer et BPESIG0201 signaturformat, som er komform med ETSI 101 733 CAdES-BES signaturer.
Code Block |
---|
byte[] document = buf; // the excact binary representation of the document
String sessionId = request.getSession().getId();
String sessionCookie = "JSESSIONID=" + sessionId;
// generate a required SHA-1 hash for the document
MessageDigest dig = MessageDigest.getInstance("SHA1");
dig.update(document);
byte[] hash = dig.digest();
// generate a base64 encoded encryption key
// that we're gonna use to encrypt the document
String b64EncryptionKey = BxCrypto.generateBase64EncodedKey();
// encrypt the document
byte[] encryptedDocument = BxCrypto.
encryptDataWithBase64EncodedKey(b64EncryptionKey, document);
// make the document available on session, so that the
// getcontent.jsp can reach it
request.getSession().setAttribute("document", encryptedDocument);
request.getSession().setAttribute("document-type", "application/pdf");
// build request data
BxElement srd = new BxElement("SignRequestData");
srd.addElement("RequestId", BxCrypto.generateUid());
srd.addElement("ResponseUrl",
"http://mysite.com/processsignresponse.do");
// choose fullsize GUI
srd.addElement("RequestAttribute", new String[]
{"name"}, new String[] {"ips:GUI"});
srd.getElement("RequestAttribute", 0).setValue("WIPSGUI-FULLSIZE");
// add the transfer encryption key
srd.addElement("TransferEncryptionKey", new String[]
{"Encoding"}, new String[]
{"ips:Base64"});
srd.getElement("TransferEncryptionKey", 0).
setValue(b64EncryptionKey);
// add the session cookie
srd.addElement("ContentCookie", sessionCookie);
// add the current time
String claimedSigningTime = BxElement.getDatTime();
srd.addElement("MerchantSigningTime", claimedSigningTime);
// add the signature format, we need compliance with
// ETSI 101 733 CAdES-BES signatures
srd.addElement("SignatureFormat", "BPESIG0201");
// add the document format/mime-type
srd.addElement("ContentMimeType", "application/pdf");
// add the document URL
srd.addElement("ContentUri", "http://mysite.com/getcontent.jsp?what=document");
// add the SHA-1 hash over the document
srd.addElement("ContentHash",
new String[] {"Encoding"},
new String[] {"ips:HexEncoding"});
// If we want to use SHA2, the Algorithm attribute must be added, so use instead:
//srd.addElement("ContentHash",
// new String[] {"Encoding", "Algorithm"},
// new String[] {"ips:HexEncoding", "ips:SHA256"});
srd.getElement("ContentHash", 0).
setValue(StrFormat.hexify(hash));
// add the description
srd.addElement("ContentDescription",
new String[] {"Encoding"},
new String[] {"ips:Plain"});
srd.getElement("ContentDescription", 0).
setValue("Signering av et eksempel dok");
BxRequest req = new BxRequest("SignRequest", srd, true);
// get the form data
String pse = req.getPSE();
String e = req.getE();
// make request object available on session
request.getSession().setAttribute("signreq", req); |
Relevante elementer å forholde seg til ifm sammensetting av en signeringsforespørsel er:
SignRequest
SignRequestData
SignResponseData
ResponseURL
RequestAttribute
ResponseAttribute
Tilgjengeliggjøring av dokumentet for sluttbrukeren
Dokumentet må tilgjengeliggjøres for signeringsklienten som nevnt over. Under er et eksempel på hvordan en "getcontent.jsp", som det refereres til i eksempelet over, kan se ut. Eksempelet er en JSP fil, som kjøres på Tomcat (ref work-around for tomcat i eksempelet under). Koden under er kun ment som et eksempel og for å komplettere forståelsen av sammenhengen i de vedlagte eksempelkodene.
Code Block |
---|
getcontent.jsp
<%
// get content and content type from session,
// based on the "what" request parameter
byte[] content = (byte[])request.getSession().
getAttribute(request.getParameter("what"));
String contentType = (String)request.getSession().
getAttribute(request.getParameter("what") + "-type");
if(content == null){
response.sendError(404, "requested content not found");
return;
}
// reset header to get around charset bug 24970 for tomact 4.1.x
// (http://www.mail-archive.com/tomcat-dev@jakarta.apache.org/msg61011.html)
response.reset();
response.setContentType(contentType);
response.setContentLength(content.length);
response.getOutputStream().write(content);
response.getOutputStream().flush();
%> |
Redirigering/sending av forespørselen til IPS
Når signeringsforespørselen er satt sammen og klar, må den sendes til IPS. Dette gjøres ved å sende PSE og E parameteren til IPS, sammen med OP (operasjonstype) og M (merchantID) parameterene i en HTML form. HTML form'en returneres tilbake til nettleseren, og sendes automatisk til IPS (v.h.a. "auto-submit"/submit på body-on-load eventen). Under er et eksempel på en side som gjør dette basert på "pse" og "e" variablene fra det første eksempelet over. I eksempelet under er merchantID=32.
Code Block |
---|
<html>
<body
onload="javascript:document.getElementById('signForm').submit()">
<form id="signForm"
action="https://secure.test4.buypass.no/wips/service"
method="POST">
<input type="hidden" name="PSE" value="<%=pse%>">
<input type="hidden" name="E" value="<%=e%>">
<input type="hidden" name="M" value="32">
<input type="hidden" name="op" value="BXSIGN">
</form>
</body>
</html> |
Javascript støtte er påkrevd i nettleseren for bruk av IPS.
Mottak og tolking av responsen
Returdataene fra signeringen "kommer tilbake" til brukerstedet på samme måte som de ble sendt til IPS. Det vil si at IPS vil returnere signeringsresponsen tilbake til nettleseren, som vil bli POST'et tilbake til brukerstedet på anngitt adresse (ResponseUrl).
Parameteren som inneholder returverdiene heter PE. Denne leses typisk ved å kalle
Code Block |
---|
String pe = request.getParameter("PE"); |
i en JSP fil. For å kunne dekryptere denne, må det korresponderende BxRequest objektet være tilgjengelig. I eksempelene over, ble dette lagt på sesjonsobjektet for å kunne brukes til dekryptering av responsen. Her er et eksempel på lesing, dekryptering og parsing:
Code Block |
---|
// parse response data
BxResponse res = new BxResponse(request.getParameter("PE"));
res.setRequestContext((BxRequest)request.getSession().
getAttribute("signreq"));
res.parse(); |
I koden over har nå BxRequest objektet fra sesjonen blitt tilordnet responsen, og responsen er dekryptert og parset. Neste steg blir å lese ut dataene fra responseobjektene.
Code Block |
---|
// get id response object
BxElement signResponseData = res.getElement("SignResponseData");
// get response status
String status = signResponseData.getElement("ResponseCode").getValue();
out.println("Status: " + status + "");
if(status.equals("ips:SUCCESS")){
// get the base64 encoded certifcate from response
String scert = signResponseData.getElementValue("Certificate");
// get the base64 encoded signature from response
String ssign = signResponseData.getElementValue("Signature");
} |
Sertifikat og signatur er nå hentet ut å ligger i scert
og ssign
variablene.
Sammensetting og
verifisering av
signaturobjektene
Under er et eksempel på sammensetning av SDO'en basert på response dataene fra eksempelet over. Etter å ha lest ut response dataene (i eksempelet over), bruker vi sertifikatet, signaturen, dokumentet og signeringstidspunktet til å generere PKCS#7 strukturen. Deretter verifiseres denne.
Code Block |
---|
byte[] content = // the document
Date signingTime = // the signing time
// ...
if(status.equals("ips:SUCCESS")){
// we want to encode a PKCS#7/CAdES-BES signature
SignatureProvider ep = SignatureProvider.getInstance("BPESIG0201");
ep.initializeForEncode("CMS_SIGNED_DATA_OBJECT");
// add all required parameters
ep.setParam("CONTENT", content);
ep.setParam("CLAIMED_SIGNING_TIME", signingTime);
ep.setParam("CERTIFICATE", (byte[])Base64Util.decodeBase64(scert));
ep.setParam("SIGNATURE", (byte[])Base64Util.decodeBase64(ssign));
// encode the structure
byte[] pkcs7 = ep.encode();
// we also want to verify the pkcs7 signature
SignatureProvider vp = SignatureProvider.getInstance("BPESIG0201");
vp.initializeForVerify("CMS_SIGNED_DATA_OBJECT_INTEGRITY");
vp.setParam("CMS_SIGNED_DATA_OBJECT", pkcs7);
boolean verifiedOk = vp.verify();
BxElement idTokenData = null;
BxElement idToken = signResponseData.getElement("IdToken");
idTokenData = idToken.getElement("IdTokenData");
// dump results
out.println("Signed by " + idTokenData.getElement("FirstName").
getValue() + " " + idTokenData.getElement("LastName").
getValue() + "");
out.println("Signature verified OK: " + verifiedOk+ "");
out.println("PKCS7 size: " + pkcs7.length + "");
}
|