1

When I use RSA to encrypt/decrypt the data,they are working good in delphi.But when I use them with other program, they seems not work.

I use the golang 1.5 in server side,when I use EncryptOAEP/DecryptOAEP,EncryptPKCS1v15/DecryptPKCS1v15,these pair functions are all good.

When I try to put all of these together,they can't recognized each other,I tried lots of kind of combination,for their own,they work fine.

1.Delphi xe6 2.lockbox Release v3.6.3.0 3.some code

golang on serverside

import (
    "errors"    
    "strings"
    "strconv"
    "log"
    "database/sql"
    _ "github.com/go-sql-driver/mysql"
    //"strconv"
    "encoding/base64"
    "encoding/json"
    "bytes"
    //"strings"
)

var privateKey = []byte(`
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDZsfv1qscqYdy4vY+P4e3cAtmvppXQcRvrF1cB4drkv0haU24Y
7m5qYtT52Kr539RdbKKdLAM6s20lWy7+5C0DgacdwYWd/7PeCELyEipZJL07Vro7
Ate8Bfjya+wltGK9+XNUIHiumUKULW4KDx21+1NLAUeJ6PeW+DAkmJWF6QIDAQAB
AoGBAJlNxenTQj6OfCl9FMR2jlMJjtMrtQT9InQEE7m3m7bLHeC+MCJOhmNVBjaM
ZpthDORdxIZ6oCuOf6Z2+Dl35lntGFh5J7S34UP2BWzF1IyyQfySCNexGNHKT1G1
XKQtHmtc2gWWthEg+S6ciIyw2IGrrP2Rke81vYHExPrexf0hAkEA9Izb0MiYsMCB
/jemLJB0Lb3Y/B8xjGjQFFBQT7bmwBVjvZWZVpnMnXi9sWGdgUpxsCuAIROXjZ40
IRZ2C9EouwJBAOPjPvV8Sgw4vaseOqlJvSq/C/pIFx6RVznDGlc8bRg7SgTPpjHG
4G+M3mVgpCX1a/EU1mB+fhiJ2LAZ/pTtY6sCQGaW9NwIWu3DRIVGCSMm0mYh/3X9
DAcwLSJoctiODQ1Fq9rreDE5QfpJnaJdJfsIJNtX1F+L3YceeBXtW0Ynz2MCQBI8
9KP274Is5FkWkUFNKnuKUK4WKOuEXEO+LpR+vIhs7k6WQ8nGDd4/mujoJBr5mkrw
DPwqA3N5TMNDQVGv8gMCQQCaKGJgWYgvo3/milFfImbp+m7/Y3vCptarldXrYQWO
AQjxwc71ZGBFDITYvdgJM1MTqc8xQek1FXn1vfpy2c6O
-----END RSA PRIVATE KEY-----
`)
var publicKey = []byte(`
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDZsfv1qscqYdy4vY+P4e3cAtmv
ppXQcRvrF1cB4drkv0haU24Y7m5qYtT52Kr539RdbKKdLAM6s20lWy7+5C0Dgacd
wYWd/7PeCELyEipZJL07Vro7Ate8Bfjya+wltGK9+XNUIHiumUKULW4KDx21+1NL
AUeJ6PeW+DAkmJWF6QIDAQAB
-----END PUBLIC KEY-----
`)
type DebugKeysRPC_Args struct {

}
type DebugKeysRPC_Reply struct {
    PubN        string
    PubE        uint64
    PrvN        string
    PrvD        string
    PrvP        string
    PrvQ        string
    Dp          string
    Dq          string
    Qinv        string
    CRTValues   string
    ID      uint64
    Key     string
    Dest    string  
}

func (t *AccessDB) DebugKeysRPC(args *DebugKeysRPC_Args, reply *DebugKeysRPC_Reply) error { 
    log.Println("DebugKeysRPC")

    if pubN,pubE,PrvN,PrvD,PrvP,PrvQ,Dp,Dq,Qinv,CRTValues,err:=ReadKeyFields(publicKey,privateKey);err==nil{
        log.Println("ok read")
        reply.PubN=base64.StdEncoding.EncodeToString(pubN)
        reply.PubE=uint64(pubE)
        reply.PrvN=base64.StdEncoding.EncodeToString(PrvN)
        reply.PrvD=base64.StdEncoding.EncodeToString(PrvD)
        reply.PrvP=base64.StdEncoding.EncodeToString(PrvP)
        reply.PrvQ=base64.StdEncoding.EncodeToString(PrvQ)
        reply.Dp=base64.StdEncoding.EncodeToString(Dp)
        reply.Dq=base64.StdEncoding.EncodeToString(Dq)
        reply.Qinv=base64.StdEncoding.EncodeToString(Qinv)
        reply.CRTValues=base64.StdEncoding.EncodeToString(CRTValues)
        reply.ID=1
        //origData:=[]byte("abcdefghijklmnopqrstuvwxyz")
        origData:=[]byte("1234567890123456")
        if resultRsa,err:=DbgRasEncryptOAEP(origData,publicKey);err==nil{
        //if resultRsa,err:=RsaEncrypt(origData,publicKey);err==nil{
            log.Printf("resultRsa(%d): % x", len(resultRsa),resultRsa)
            reply.Dest=base64.StdEncoding.EncodeToString(resultRsa)
            if resultRsaP,err:=DbgRsaDecryptOAEP(resultRsa,privateKey);err==nil{
                //log.Printf("RsaDecrypt ok % x", resultRsaP)   
                log.Println("RsaDecrypt ok")
                log.Printf("resultRsaP(%d): %s", len(string(resultRsaP)),string(resultRsaP))
            }else{
                log.Println("RsaDecrypt",err)
            }
        }else{
            log.Println("RsaEncrypt",err)
        }                   
    }else{
        WatchPublicKey(publicKey)
        WatchPrivateKey(privateKey)
        log.Println(err)
    }

    return nil
}

=============================================================================== some code in delphi side(I haven't install the lockbox,I insert all source into project).

===============================================================================

procedure RsaEncrypt( const PublicKey: TStream; const srcStream : TStream;tgtStream:TStream);
var
  Codec : TCodec;
  wasAborted: boolean;
  KeyPair: TAsymetricKeyPair;
  Key: TSymetricKey;
  lib : TCryptographicLibrary;
begin
  Codec := TCodec.Create(Nil);
  lib := TCryptographicLibrary.Create(Nil);
  try
    //0. Reset
    Codec.Reset;
    Codec.CryptoLibrary := lib;
    Codec.ChainModeId := ECB_ProgId;
    Codec.StreamCipherId := 'native.RSA';

    //1. Set the cipher to RSA encryption.
    Codec.StreamCipherId := RSA_ProgId;

    //2. Load our pre-fabricated public key.
    PublicKey.Position := 0;
    Codec.AsymetricKeySizeInBits := 1024;
    Key := Codec.Asymetric_Engine.CreateFromStream(PublicKey, [partPublic]);

    //3. Now set the key.
    Codec.InitFromKey(Key);
    Codec.EncryptStream(srcStream,tgtStream);
  finally
    lib.Free;
    Codec.Free;
  end;
end;

procedure RsaDecrypt( const PrivateKey: TStream; const srcStream : TStream;tgtStream:TStream);
var
  Codec : TCodec;
  wasAborted: boolean;
  KeyPair: TAsymetricKeyPair;
  //Key: TSymetricKey;
  lib : TCryptographicLibrary;
begin
  Codec := TCodec.Create(Nil);
  lib := TCryptographicLibrary.Create(Nil);
  try
   //0. Reset
   Codec.Reset;
   Codec.CryptoLibrary := lib;
   Codec.ChainModeId := ECB_ProgId;
   Codec.StreamCipherId := 'native.RSA';

    //1. Set the cipher to RSA encryption.
    Codec.StreamCipherId := RSA_ProgId;

    //2. Load our pre-fabricated private key.
    PrivateKey.Position := 0;
    Codec.AsymetricKeySizeInBits := 1024;
    KeyPair := Codec.Asymetric_Engine.CreateFromStream(PrivateKey, [partPrivate]);

    //3. Now set the key.
    Codec.InitFromKey(KeyPair);

    Codec.DecryptStream(tgtStream,srcStream);
  finally
    lib.Free;
    Codec.Free;
  end;
end;

procedure Sign(privateKey,srcStream,tgtStream:TMemoryStream);
var
  sign:TSignature;
begin
  try
    sign:=TSignature.Create;
    privateKey.Seek(0,soBeginning);
    sign.m_Signatory.LoadKeysFromStream(privateKey,[partPrivate]);

    sign.m_Signatory.Sign(srcStream,tgtStream);
  finally
    sign.Free;
  end;
end;

function Verify(publicKey,srcStream,tgtStream:TMemoryStream):Boolean;
var
  sign:TSignature;
  vResult:TVerifyResult;
  nDbg:Integer;
begin
  try
    result:=False;
    publicKey.Seek(0,soBeginning);
    srcStream.Seek(0,soBeginning);
    tgtStream.Seek(0,soBeginning);
    sign:=TSignature.Create;
    sign.m_Signatory.LoadKeysFromStream(publicKey,[partPublic]);

    vResult:=sign.m_Signatory.Verify(srcStream,tgtStream);
    if vResult=vPass then
    begin
      nDbg:=0;
      result:=True;
    end
    else if vResult=vFail then
    begin
      nDbg:=1;
    end
    else if vResult=vUserAbort then
      nDbg:=3
    else nDbg:=4;
  finally
    sign.Free;
  end;
end;

procedure readPubKey(pubN:TStream;pubE:TStream);
var
  publicKey:TMemoryStream;
  Codec : TCodec;
  Key: TAsymetricKeyPair;
  lib : TCryptographicLibrary;
begin
  try
    publicKey:=TMemoryStream.Create;

    publicKey.LoadFromFile('e:\public.key');

    Codec := TCodec.Create(Nil);
    lib := TCryptographicLibrary.Create(Nil);
    try
      //0. Reset
      Codec.Reset;
      Codec.CryptoLibrary := lib;
      Codec.ChainModeId := ECB_ProgId;

      //1. Set the cipher to RSA encryption.
      Codec.StreamCipherId := RSA_ProgId;

      //2. Load our pre-fabricated public key.
      PublicKey.Position := 0;
      Codec.AsymetricKeySizeInBits := 1024;
      Key := Codec.Asymetric_Engine.CreateFromStream(publicKey, [partPublic]);
      //pubN.Write(Key.F_RSA_n.Value,sizeof(Key.F_RSA_n.Value));
      //pubE.Write(Key.F_RSA_n.Value,sizeof(Key.F_RSA_e.Value));
      pubN.CopyFrom((TRSAKeyPair(Key)).F_RSA_n.Value.FValue,0);
      pubE.CopyFrom((TRSAKeyPair(Key)).F_RSA_e.Value.FValue,0);
    finally
      lib.Free;
      Codec.Free;
    end;

  finally
    publicKey.Free;
  end;
end;

procedure dbgRsaKeys();
var
  publicKey:TMemoryStream;
  privateKey:TMemoryStream;
  tgtStream:TMemoryStream;
  srcStream:TStringStream;
  src:string;
  rstStream:TStringStream;
  sResult:string;
begin
  publicKey:=TMemoryStream.Create;
  privateKey:=TMemoryStream.Create;
  rstStream:=TStringStream.Create;
  srcStream:=TStringStream.Create;
  tgtStream:=TMemoryStream.Create;
  try
    src:='tell me why,tell me how,tell me where';
    srcStream.WriteString(src);
    srcStream.Seek(0,soBeginning);
    publicKey.LoadFromFile('e:\public.key');
    privateKey.LoadFromFile('e:\private.key');

    RsaEncrypt( PublicKey,srcStream ,tgtStream);

    RsaDecrypt( PrivateKey,tgtStream,rstStream);
    sResult:=rstStream.DataString;
  finally
    publicKey.Free;
    privateKey.Free;
    srcStream.Free;
    tgtStream.Free;
    rstStream.Free;
  end;
end;
procedure TestEncrypt();
var
  publicKey:TMemoryStream;
  srcStream,tgtStream:TMemoryStream;
begin
  try
    publicKey:=TMemoryStream.Create;

    srcStream:=TMemoryStream.Create;
    srcStream.LoadFromFile('e:\scanconfig.txt');
    tgtStream:=TMemoryStream.Create;
    publicKey.LoadFromFile('e:\public.key');

    RsaEncrypt( PublicKey,srcStream ,tgtStream);

    tgtStream.SaveToFile('e:\scanconfig.enc');
  finally
    publicKey.Free;
    srcStream.Free;
    tgtStream.Free;
  end;
end;

procedure TestDecrypt(srcStream:TMemoryStream);
var
  privateKey:TMemoryStream;
  tgtStream:TStringStream;
  sResult:String;
begin
  //dbgRsaKeys();
  privateKey:=TMemoryStream.Create;
  tgtStream:=TStringStream.Create;
  try
    srcStream.Seek(0,soBeginning);
    privateKey.LoadFromFile('e:\private.key');
    RsaDecrypt( privateKey,srcStream,tgtStream);
    sResult:=tgtStream.DataString;
  finally
    privateKey.Free;
    tgtStream.Free;
  end;
end;

================================================================================

BugHunter
  • 11
  • 1
  • 2

1 Answers1

0

The TP Lockbox 3 native RSA codec implements RSA/PKCS#1 version 2.1 (http://www.ietf.org/rfc/rfc3447.txt). This algorithm is parameterized by the choice of hash function and mask generation function. If two RSA codecs have different hash function or mask generation function, they will not be interoperable.

The hash function and the mask generation function in LB3, can be found in procedure MGF1() in unit TPLB3.RSA_Primitives, and is based on SHA-1. You would have to find out what hash and mask generation function goLang uses to find out if there is even a chance for interoperability. The standard gives recommendations (which were adopted by LB3), but none are standardised.

As well as that, it appears from your goLang listing, that goLang encooding the keys in PEM format. LB3's native RSA does not use the PEM format.

For your best chance at interoperability, try LB's OpenSSL component instead of the native RSA codec.

For Delphi to Delphi, LB3 is a great cryptographic library. Very flexible, modular, with plenty of ciphers and block chaining methods, and the only FOSS library I know with a published and extensive set of unit tests. But its great weakness is interoperability. If interoperability between other languages or systems is important, then you should probably choose another library.

Sean B. Durkin
  • 12,659
  • 1
  • 36
  • 65
  • Thanks for your answer.You remind me the difference of hash,I remember that I traced the RSA in lockbox to compare to Golang,it's the problem of sha-1,in Golang,you can pass a hash in. There are no demo of OpenSSL in lockbox,I even don't know how to use it.Oher RSA library for delphi? no,lockbox is the best,if lockbox can't solve,I don't think there are. Thanks for your relply again. – BugHunter Nov 24 '15 at 00:58