Ciao,
se lo scopo di queste 3 righe:
sl:=TStringList.Create;
sl.LoadFromFile(Edit1.Text);
sfile:=sl.Text;
sl.Free;
è quello di salvare l'intero file in una stringa, credo che usare la TStringList ti potrebbe creare problemi: sl.Text potrebbe contenere i caratteri di fine linea, che di solito vengono usati tra una riga della TStringList e la successiva.
Secondo me, ti conviene usare uno TFileStream, anche se provando ad usarlo p rimane sempre non assegnata.
Questo è il tuo codice "riadattato":
procedure TForm1.Sproteggi2(NomeFilePart, NomeFileDest: String);
var FBIO: PBIO;
sfile: AnsiString;
FileStreamPart:TFileStream;
i: integer;
p: SslPtr;
DimFile, BytesLetti:Int64;
begin
//Apro il file di partenza e faccio in modo che non sia vincolato dal processo in corso
FileStreamPart:=TFileStream.Create(NomeFilePart, CstApriFileSolaLett);
try
DimFile:=FileStreamPart.Size;
sfile:=StringOfChar(#32, DimFile);
BytesLetti:=FileStreamPart.Read(PChar(sfile)^, DimFile);
if (BytesLetti <> DimFile) then begin
EmettiErrore(0, 'Problemi durante la lettura del file' + NomeFilePart);
Halt;
end else begin
fbio:=BioNew(BioSMem);
i:=BioRead(FBIO, sfile, Length(sfile));
p:= d2iPKCS12bio(FBIO, nil);
BioFreeAll(FBIO);
end;
finally
FreeAndNil(FileStreamPart);
end;
end;
P.S. Dopo l'esecuzione dell'istruzione
i:=BioRead(FBIO, sfile, Length(sfile));
i vale "-1", quindi probabilmente il problema nasce lì.
Ciao, Mario
Questa funziona
fBIO := BIO_new_file(nomefile, 'r'); // Read from stream
Puoi postare il codice?
Io ho fatto così, ma p rimane sempre "vuota"
fBIO := BIO_new_file(PChar(NomeFilePart), 'r'); // Read from stream
p:= d2iPKCS12bio(FBIO, nil);
BioFreeAll(FBIO);
Ciao, MArio
ho cercato di mettere un po' d'ordine nei sorgenti e li metto qua per chi voglia fare qualche esperimento
vabbè, ordine si fa per dire... :)
ora dovrei capire bene come procedere, non vi nego che per me il da farsi è ancora un po' oscuro, ma un passetto alla volta spero di arrivare in fondo
allo stadio attuale si riesce a leggere il file "partenza" e a passare il contenuto da una struttura BIO_in (input)
se non ho capito male ora bisognerebbe fare una trascodifica verso una struttura BIO_out
se qualcuno ne sa più di me mi chiarisca pure :)
procedure TForm1.Sproteggi2(NomeFilePart, NomeFileDest: String);
var FBIO_in, FBIO_out: PBIO;
sfile: AnsiString;
FileStreamPart:TFileStream;
i: integer;
p: SslPtr;
DimFile, BytesLetti:Int64;
pmem: PChar;
begin
// init
BytesLetti:=-1;
// Apro il file di partenza e carico il centenuto in un buffer
FileStreamPart:=TFileStream.Create(NomeFilePart, fmOpenRead);
try
DimFile:=FileStreamPart.Size;
sfile:=StringOfChar(#0, DimFile);
FileStreamPart.Position:=0;
pmem:=addr(sfile[1]);
BytesLetti:=FileStreamPart.Read(pmem^, DimFile);
finally
FreeAndNil(FileStreamPart);
end;
// test errore lettura
if BytesLetti <> DimFile then
exception.Create('Errore nella lettura del file sorgente');
// inizio estrazione
FBIO_in:=BioNew(BioSMem);
FBIO_out:=BioNew(BioSMem);
try
// assegno buffer letto a BIO_IN
i:=BioWrite(FBIO_in, sfile, BytesLetti);
if i<=0 then
exception.Create('Errore scrittura in BIO_in');
// trascodifica in BIO_OUT
// p:= d2iPKCS12bio(FBIO, nil);
finally
BioFreeAll(FBIO_in);
BioFreeAll(FBIO_out);
end;
end;
sono riuscito a fare un'altro passetto:
Edit:
come già riportato da giuian
Rimane vuota perché devi usare d2ipkcs7bio ...
Ci sono molte funzioni openssl che non sono presenti in openssl.pas, ma si possono aggiungere chiaramente.
la funzione d2iPKCS7bio non era esportata da ssl_openssl_lib e quindi mi sono arrangiato dichiarando il tutto a mano, seguendo il codice di d2iPKCS12bio.
Per ora non ho fatto modifiche in ssl_openssl_lib, è tutto nel codice quì sotto, lo riporto così come viene compilato nel mio progetto (un form vuoto con un bottone).
Girando per la rete ho trovato questo
https://gist.github.com/HungHuynh/3810968 (https://gist.github.com/HungHuynh/3810968)
probabilmente le prossime funzioni che serviranno saranno PEM_read_bio_PKCS7 e/o OBJ_obj2nid
implementation
{$R *.lfm}
uses synafpc;
type
Td2iPKCS7bio = function(b:PBIO; Pkcs7: SslPtr): SslPtr; cdecl;
// TPKCS7parse = function(p7: SslPtr; pass: PAnsiChar; var pkey, cert, ca: SslPtr): integer; cdecl;
// TPKCS12free = procedure(p12: SslPtr); cdecl;
var
_d2iPKCS7bio: Td2iPKCS7bio = nil;
function GetProcAddr(module: HModule; const ProcName: string): SslPtr;
begin
Result := GetProcAddress(module, PChar(ProcName));
end;
function d2iPKCS7bio(b:PBIO; Pkcs7: SslPtr): SslPtr;
begin
if InitSSLInterface and Assigned(_d2iPKCS7bio) then
Result := _d2iPKCS7bio(b, Pkcs7)
else
Result := nil;
end;
{ TForm1 }
procedure TForm1.Button2Click(Sender: TObject);
begin
Sproteggi2(Edit1.Text, ExtractFilePath(Edit1.Text) + 'out.dat');
end;
procedure TForm1.Sproteggi2(NomeFilePart, NomeFileDest: String);
var FBIO_in, FBIO_out: PBIO;
sfile: AnsiString;
FileStreamPart:TFileStream;
i: integer;
p: SslPtr;
DimFile, BytesLetti:Int64;
pmem: PChar;
begin
// init
BytesLetti:=-1;
_d2iPKCS7bio := Td2iPKCS7bio(GetProcAddress(SSLUtilHandle, 'd2i_PKCS7_bio'));
// _PKCS12parse := GetProcAddr(SSLUtilHandle, 'PKCS12_parse');
// _PKCS12free := GetProcAddr(SSLUtilHandle, 'PKCS12_free');
// Apro il file di partenza e carico il centenuto in un buffer
FileStreamPart:=TFileStream.Create(NomeFilePart, fmOpenRead);
try
DimFile:=FileStreamPart.Size;
sfile:=StringOfChar(#0, DimFile);
FileStreamPart.Position:=0;
pmem:=addr(sfile[1]);
BytesLetti:=FileStreamPart.Read(pmem^, DimFile);
finally
FreeAndNil(FileStreamPart);
end;
// test errore lettura
if BytesLetti <> DimFile then
exception.Create('Errore nella lettura del file sorgente');
// inizio estrazione
FBIO_in:=BioNew(BioSMem);
FBIO_out:=BioNew(BioSMem);
try
// assegno buffer letto a BIO_IN
i:=BioWrite(FBIO_in, sfile, BytesLetti);
if i<=0 then
exception.Create('Errore scrittura in BIO_in');
// trascodifica pkcs7
p:= d2iPKCS7bio(FBIO_in, nil);
if Assigned(p) then
ShowMessage('d2iPKCS7bio: eureka!');
finally
BioFreeAll(FBIO_in);
BioFreeAll(FBIO_out);
end;
end;
end.
Si proprio così.
Ora bisogna vedere la dimensione del contenuto del pkcs7, a me puntava ad un record vuoto.
La sequenza di funzioni da usare adesso è quella di questo esempio delphi
// Open a PKCS7 file
procedure TPKCS7.Open(Filename: string);
var
p7file: pBIO;
objectType: integer;
begin
p7file := BIO_new(BIO_s_file());
if p7file = nil then
raise EOpenSSL.Create('Unable to create a file handle.');
BIO_read_filename(p7file, PChar(Filename));
if (fEncoding = auto) or (fEncoding = DER) then
begin
fPkcs7 := d2i_PKCS7_bio(p7file, nil);
if (fPkcs7 = nil) and (fEncoding = auto) then
BIO_reset(p7file);
end;
if ((fPkcs7 = nil) and (fEncoding = auto)) or (fEncoding = PEM) then
begin
fPkcs7 := PEM_read_bio_PKCS7(p7file, nil, nil, nil);
if (fPkcs7 = nil) and (fEncoding = auto) then
BIO_reset(p7file);
end;
if ((fPkcs7 = nil) and (fEncoding = auto)) or (fEncoding = SMIME) then
begin
fPkcs7 := SMIME_read_PKCS7(p7file, fDetachedData); // &indata ????
end;
if fPkcs7 = nil then
raise EOpenSSL.Create('Unable to read PKCS7 file');
if p7file <> nil then
BIO_free(p7file);
objectType := OBJ_obj2nid(fPkcs7.asn1_type);
case objectType of
NID_pkcs7_signed: fCerts := fPkcs7.sign.cert;
NID_pkcs7_signedAndEnveloped: fCerts := fPkcs7.signed_and_enveloped.cert;
end;
end;
procedure TPKCS7.SaveContent(Filename: String);
var
p7bio, contentfile: pBIO;
sinfos: pSTACK_OFPKCS7_SIGNER_INFO;
i: integer;
buffer: array [0..4096] of char;
begin
if fPkcs7 = nil then
raise EOpenSSL.Create('No PKCS7 content.');
if OBJ_obj2nid(fPkcs7.asn1_type) <> NID_pkcs7_signed then
raise EOpenSSL.Create('Wrong PKCS7 format.');
if (PKCS7_get_detached(fPkcs7) <> nil)
and (fDetachedData = nil) then
raise EOpenSSL.Create('PKCS7 has no content.');
sinfos := PKCS7_get_signer_info(fPkcs7);
if (sinfos = nil) or (sk_num(sinfos) = 0) then
raise EOpenSSL.Create('No signature data.');
contentfile := BIO_new(BIO_s_file());
if BIO_write_filename(contentfile, PChar(Filename)) <= 0 then
raise EOpenSSL.Create('Error creating output file.');
p7bio := PKCS7_dataInit(fPkcs7, fDetachedData);
repeat
i := BIO_read(p7bio, @buffer, SizeOf(buffer));
if i > 0 then
BIO_write(contentfile, @buffer, i);
until i <= 0;
if fDetachedData <> nil then
BIO_pop(p7bio);
BIO_free_all(p7bio);
BIO_free(contentfile);
end;
In delphi dichiarano una classe
TPKCS7 = class
private
fEncoding: TEncoding;
fPkcs7: pPKCS7;
fCerts: pSTACK_OFX509;
fDetachedData: pBIO;
protected
function countCerts: integer;
function getCert(i: integer): TX509Certificate;
public
constructor Create;
destructor Destroy; override;
property Encoding: TEncoding read fEncoding write fEncoding default auto;
property CountCertificate: integer read countCerts;
property Certificate[Index: Integer]: TX509Certificate read getCert;
procedure Open(FileName: string);
procedure Save(Filename: String); overload;
procedure Save(Filename: String; Encoding: TEncoding); overload;
procedure SaveContent(Filename: String);
function VerifyData: boolean; overload;
function VerifyData(Content: pointer): boolean; overload;
end;
Ma nel mio adattamento qualcosa non va.
La funzione di Openssl è
#define PKCS7_get_detached ( p ) PKCS7_ctrl(p,PKCS7_OP_GET_DETACHED_SIGNATURE,0,NULL)
#define PKCS7_OP_SET_DETACHED_SIGNATURE 1
#define PKCS7_OP_GET_DETACHED_SIGNATURE 2