📄 srp.pas
字号:
{Copyright: Hagen Reddmann HaReddmann at T-Online dot de
Author: Hagen Reddmann
Remarks: this Copyright must be included
known Problems: none
Version: 5.1, Part II from Delphi Encryption Compendium
Delphi 5
Description: Counter-SRP, modified Secure Remote Password Protocoll
based on SRP-6a
All Interfaced are declared to support own DLL's to
other languages that supports COM Objects. Thus the use of
WideString.
Normaly the programmer provide a custom ISRPDatabase Interface
to he's own Database of Users. Such Database have only two
columns -> Identifier and Data of type String.
Here we provide two such ISRPDatabase Impelmentation:
- in textbased INI Files
- in Registry of current user
The ISRPDatabase Interface are most globaly used and must provide
a threadsafe way to access the records, eg. should use RTL-
Critical Sections.
The ISRPServer and ISRPClient are only allocated live in the
Connections Threads of our TCP/IP Library, as example iff we use
INDY componnents the we allocate these Interfaces in the threaded
TCP/IP Method of TidTCPServer and TidTCPClient.
This is because that a ISRPClient/ISRPSever Interface holds only
one current session of one attemp for secret sharing.
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
}
{$I VER.INC}
unit SRP;
interface
type
ISRPDatabase = interface
['{FCFBEF2F-1C57-401D-BACC-10CDC6252A78}']
function Lookup(const Ident: WideString): WideString; stdcall;
procedure Store(const Ident, Data: WideString); stdcall;
procedure Delete(const Ident: WideString); stdcall;
end;
TSRPState = (srpNone, srpStep0, srpStep1, srpFinish);
ISRPServer = interface
['{82A45C14-A133-4C26-AF61-DA1DD59AB3EE}']
function State: TSRPState; stdcall;
function SharedSecret: WideString; stdcall;
function Counter: Cardinal; stdcall;
function Identifier: WideString; stdcall;
function Encrypt(const Msg: WideString): WideString; stdcall;
function Decrypt(const Msg: WideString): WideString; stdcall;
function Step0(const Msg: WideString): WideString; stdcall;
function Step1(const Msg: WideString): WideString; stdcall;
function RegisterClient(const Name: WideString): WideString; stdcall;
end;
ISRPClient = interface
['{A690EE81-A46A-4FC9-B55F-88EE3D665E6C}']
function State: TSRPState; stdcall;
function SharedSecret: WideString; stdcall;
function Counter: Cardinal; stdcall;
function Identifier: WideString; stdcall;
function Encrypt(const Msg: WideString): WideString; stdcall;
function Decrypt(const Msg: WideString): WideString; stdcall;
function Step0(const Name: WideString; const OldPassword: WideString; const NewPassword: WideString = ''): WideString; stdcall;
function Step1(const Msg: WideString): WideString; stdcall;
function Step2(const Msg: WideString): WideString; stdcall;
end;
// these functions should be exported if a DLL is used
function SRPDatabase(InRegistry: Boolean = False): ISRPDatabase; stdcall;
function SRPServer(const ADatabase: ISRPDatabase): ISRPServer; stdcall;
function SRPClient: ISRPClient; stdcall;
implementation
(*
Counter-SRP-6
SecureBits = integer
MGF([data]) = hash based Mask Generation Function, creates SecureBits length result
from a set of input parameters
MGF([data], index) = MGF with Index > 0
OTP(data, key, index) = hash based One Time Pad, use an indexed KDF
RND() = secure random generator, produce SecureBits result
Name = plaintext Name of Client
I = Identifier of Client
S,S' = random Password Salt, SecureBits long
Sp = public OTP encrypted Salt
V,V' = Password Verifier
Vp = public OTP encrypted Verifier
P,P' = client passwords, old and new
C = incremental Counter, 32 Bits long, used as Index in the MGF
N = large Safe Prime, so called Sophie Germain Prime
g = Generator, > 3
k = hased security value
ID = string thats represent N,G,K in safe manner
b,B = empheral server keys, secret and public
a,A = empheral client keys, secret and public
K = shared secret key
Kd = derivate of K
??? = question
CLIENT SERVER
I = MGF([Name])
-----------> I
lookup I,S,V,C,ID in Database
N,g = IDPrime(ID)
k = MGF([N, g])
b = RND()
B = k*V+g^b
S,C,B,ID <---
B = 0 ??? abort else ok
N,g = IDPrime(ID)
k = MGF([N, g])
x = MGF([S, I, P], C)
V = g^x
a = RND()
A = g^a
u = MGF([A, B], C)
K = (B-k*V)^(a+u*x)
S' = RND()
x' = MGF([S', I, P'], C +1)
V' = g^x'
Vp = OTP(V', K, C +1)
Sp = OTP(S', K, C +1)
Mc = MGF([A, B, S', V'])
----> Mc,A,Sp,Vp
A = 0 ??? abort else ok
u = MGF([A, B], C)
K = (A*V^u)^b
S' = OTP(Sp, K, C +1)
V' = OTP(Vp, K, C +1)
M' = MGF([A, B, S', V'])
M' = Mc ??? ok else abort
Mh = MGF([A, B, S', V', Mc])
store
I,S=S',V=V',C=C+1
Mh <---------
M' = MGF([A, B, S', V', Mc])
M' = Mh ??? ok else abort
Kd = MGF([K]) Kd = MGF([K])
<-Data encrypted->
*)
uses Windows, SysUtils, Registry, INIFiles, DECUtil, DECFmt, DECHash, DECCipher,
DECRandom, NMath, NInts, IDPrimes;
const
SRP_HashClass : TDECHashClass = THash_SHA1;
SRP_CipherClass : TDECCipherClass = TCipher_Blowfish;
SRP_SecureBits : Integer = 256;
SRP_Separator : String = ';'; // don't use same separator as for ID-Primes !!
SRP_Format : TStrFormat = (
Base: 64;
Plus: '';
Minus: '';
Zero: '';
Comma: ',';
DigitsPerBlock: 0;
BlockSep: #0;
BlockPadding: #0;
DigitsPerLine: 0;
LineSep: #13#10;
LinePadding: #0;
DigitsChars: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
FormatChars: ' /\-+;:#~"()[]?_<>!
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -