我终于在delphi中完成了SRP协议的实现! 使用openssl库计算哈希值和Bignum。
最后的实施并不复杂。但我有疑问:
1)我可以使用随机对N,g。 N 4096位足够安全吗?
2)K,作为RFC 5054,是一个强会话密钥,但长度为768字节,N到4906位。那么如何才能正确使用AES256的会话密钥?
3)最后,有没有办法测试我编写的实现是否正常工作?有没有人可以给我建议?
放置代码,考虑到它尚未优化,类型N,G可能属于类var。
提前感谢所有人。
type
TSRP = class
public
class procedure CreateVerifierKey( const AIdentity, APassword: TIdBytes; var ASalt, AVerifierKey: TIdBytes );
class procedure ServerValues( const ASalt, AVerifierKey: TIdBytes; var APrivateValue, APublicValue: TIdBytes );
class procedure IdentityValues( var APrivateValue, APublicValue: TIdBytes );
class function ServerKey( const AServerPrivateValue, AServerPublicValue, AVerifierKey, AIdentityPublicValue: TIdBytes ): TIdBytes;
class function IdentityKey( const AIdentity, APassword, AIdentityPrivateValue, AIdentityPublicValue, ASalt, AServerPublicValue, AVerifierKey: TIdBytes ): TIdBytes;
class function VerifierMessage( const AUserName: String; const ASalt, AServerPublicValue, AIdentityPublicValue, AKey: TIdBytes ): TIdBytes;
end;
{ TSRP }
class procedure TSRP.CreateVerifierKey( const AIdentity, APassword: TIdBytes; var ASalt, AVerifierKey: TIdBytes );
var
N: PBIGNUM;
G: PBIGNUM;
S: PBIGNUM;
X: PBIGNUM;
V: PBIGNUM;
C: PBN_CTX;
begin
S := BIGNUM;
try
BN_rand( S, 48, - 1, 0 );
ASalt := BN_bytes( S );
finally
BN_free( S );
end;
X := BIGNUM( TIdSha512Hash.Digest( TIdBytes.From( ASalt ).Append( AIdentity ).Append( APassword ) ) );
N := BIGNUM( TIdBase64.Decode( SRP_NG_4096_N ) );
G := BIGNUM( [ 5 ] );
C := BN_CTX_new;
V := BN_new;
BN_mod_exp( V, G, X, N, C );
SetLength( AVerifierKey, TIdSha512Hash.Size );
AVerifierKey := BN_bytes( V );
BN_free( X );
BN_free( N );
BN_free( G );
BN_free( V );
BN_CTX_free( C );
end;
class procedure TSRP.ServerValues( const ASalt, AVerifierKey: TIdBytes; var APrivateValue, APublicValue: TIdBytes );
var
G: PBIGNUM;
N: PBIGNUM;
K: PBIGNUM;
B: PBIGNUM;
R: PBIGNUM;
A: PBIGNUM;
V: PBIGNUM;
C: PBN_CTX;
begin
B := BIGNUM;
BN_rand( B, 256, - 1, 0 );
APrivateValue := BN_bytes( B );
N := BIGNUM( TIdBase64.Decode( SRP_NG_4096_N ) );
G := BIGNUM( [ 5 ] );
K := BIGNUM( TIdSha512Hash.Digest( TIdBytes.From( BN_Bytes( N ) ).Append( BN_Bytes( G ) ) ) );
R := BIGNUM;
A := BIGNUM;
V := BIGNUM;
C := BN_CTX_new;
BN_mul( R, K, BIGNUM( AVerifierKey ), C );
BN_mod_exp( A, G, B, N, C );
BN_add( V, R, A );
APublicValue := BN_bytes( V );
BN_free( V );
BN_free( A );
BN_free( R );
BN_free( K );
BN_free( G );
BN_free( N );
BN_free( B );
BN_CTX_free( C );
end;
class procedure TSRP.IdentityValues( var APrivateValue, APublicValue: TIdBytes );
var
N: PBIGNUM;
G: PBIGNUM;
B: PBIGNUM;
A: PBIGNUM;
C: PBN_CTX;
begin
N := BIGNUM( TIdBase64.Decode( SRP_NG_4096_N ) );
G := BIGNUM( [ 5 ] );
B := BIGNUM;
A := BIGNUM;
BN_rand( B, 256, - 1, 0 );
APrivateValue := BN_bytes( B );
C := BN_CTX_new;
BN_mod_exp( A, G, B, N, C );
APublicValue := BN_bytes( A );
BN_free( B );
BN_free( A );
BN_free( G );
BN_free( N );
BN_CTX_free( C );
end;
class function TSRP.ServerKey( const AServerPrivateValue, AServerPublicValue, AVerifierKey, AIdentityPublicValue: TIdBytes ): TIdBytes;
var
N: PBIGNUM;
G: PBIGNUM;
A: PBIGNUM;
B: PBIGNUM;
U: PBIGNUM;
V: PBIGNUM;
T: PBIGNUM;
J: PBIGNUM;
R: PBIGNUM;
C: PBN_CTX;
begin
N := BIGNUM( TIdBase64.Decode( SRP_NG_4096_N ) );
G := BIGNUM( [ 5 ] );
A := BIGNUM( AIdentityPublicValue );
B := BIGNUM( AServerPrivateValue );
V := BIGNUM( AVerifierKey );
U := BIGNUM( TIdSha512Hash.Digest( TIdBytes.From( AIdentityPublicValue ).Append( AServerPublicValue ) ) );
T := BIGNUM;
J := BIGNUM;
R := BIGNUM;
C := BN_CTX_new;
BN_mod_exp( T, V, U, N, C );
BN_mul( J, A, T, C );
BN_mod_exp( R, J, B, N, C );
Result := BN_bytes( R );
BN_free( N );
BN_free( G );
BN_free( A );
BN_free( B );
BN_free( V );
BN_free( U );
BN_free( T );
BN_free( J );
BN_free( R );
BN_CTX_free( C );
end;
class function TSRP.IdentityKey( const AIdentity, APassword, AIdentityPrivateValue, AIdentityPublicValue, ASalt, AServerPublicValue, AVerifierKey: TIdBytes ): TIdBytes;
var
N: PBIGNUM;
G: PBIGNUM;
B: PBIGNUM;
X: PBIGNUM;
K: PBIGNUM;
A: PBIGNUM;
U: PBIGNUM;
V: PBIGNUM;
T: PBIGNUM;
L: PBIGNUM;
P: PBIGNUM;
Q: PBIGNUM;
R: PBIGNUM;
C: PBN_CTX;
begin
N := BIGNUM( TIdBase64.Decode( SRP_NG_4096_N ) );
G := BIGNUM( [ 5 ] );
B := BIGNUM( AServerPublicValue );
X := BIGNUM( TIdSha512Hash.Digest( TIdBytes.From( ASalt ).Append( AIdentity ).Append( APassword ) ) );
K := BIGNUM( TIdSha512Hash.Digest( BN_bytes( N ).Append( BN_bytes( G ) ) ) );
A := BIGNUM( AIdentityPrivateValue );
U := BIGNUM( TIdSha512Hash.Digest( TIdBytes.From( AIdentityPublicValue ).Append( AServerPublicValue ) ) );
V := BIGNUM;
T := BIGNUM;
L := BIGNUM;
P := BIGNUM;
Q := BIGNUM;
R := BIGNUM;
C := BN_CTX_new;
BN_mod_exp( V, G, X, N, C );
BN_mul( T, V, K, C );
BN_sub( L, B, T );
BN_mul( P, U, X, C );
BN_add( Q, A, P );
BN_mod_exp( R, L, Q, N, C );
Result := BN_bytes( R );
BN_free( N );
BN_free( G );
BN_free( B );
BN_free( X );
BN_free( K );
BN_free( A );
BN_free( U );
BN_free( V );
BN_free( T );
BN_free( L );
BN_free( P );
BN_free( Q );
BN_free( R );
BN_CTX_free( C );
end;
class function TSRP.VerifierMessage( const AUserName: String; const ASalt, AServerPublicValue, AIdentityPublicValue, AKey: TIdBytes ): TIdBytes;
var
N: PBIGNUM;
G: PBIGNUM;
R: PBIGNUM;
X: TIdBytes;
C: PBN_CTX;
begin
N := BIGNUM( TIdBase64.Decode( SRP_NG_4096_N ) );
G := BIGNUM( [ 5 ] );
C := BN_CTX_new;
R := BIGNUM;
BN_mul( R, G, N, C );
X := BN_bytes( R );
Result.Assign( TIdSha512Hash.Digest( TIdBytes.From( X ).Append( AUserName ).Append( ASalt ).Append( AServerPublicValue ).Append( AIdentityPublicValue ).Append( AKey ) ) );
Result.Assign( TIdSha512Hash.Digest( TIdBytes.From( AIdentityPublicValue ).Append( Result ).Append( AKey ) ) );
BN_free( N );
BN_free( G );
BN_free( R );
BN_CTX_free( C );
X.Clear;
end;
截图