55using System . Text ;
66using CyberSource . Api ;
77using CyberSource . Model ;
8- using FlexServerSDK . Exception ;
9- using FlexServerSDK . Model ;
8+ using CyberSource . Utilities . Flex . Model ;
9+ using CyberSource . Utilities . Flex . TokenVerification ;
1010
1111namespace Cybersource_rest_samples_dotnet . Samples . Flex . CoreServices
1212{
@@ -41,7 +41,9 @@ public static void Run()
4141 var result = apiInstance . Tokenize ( requestObj ) ;
4242 Console . WriteLine ( result ) ;
4343
44- var flexPublicKey = new FlexPublicKey ( keyId , new FlexServerSDK . Model . DerPublicKey ( derFormat , derAlgo , derPublicKey ) , null ) ;
44+ TokenVerificationUtility tokenVerifier = new TokenVerificationUtility ( ) ;
45+
46+ var flexPublicKey = new FlexPublicKey ( keyId , new FlexDerPublicKey ( derFormat , derAlgo , derPublicKey ) , null ) ;
4547 var flexToken = new FlexToken ( )
4648 {
4749 keyId = result . KeyId ,
@@ -63,228 +65,13 @@ public static void Run()
6365 postParameters [ "token" ] = flexToken . token ;
6466 postParameters [ "timestamp" ] = Convert . ToString ( flexToken . timestamp ) ;
6567
66- var tokenVerificationResult = Verify ( flexPublicKey , postParameters ) ;
68+ var tokenVerificationResult = tokenVerifier . Verify ( flexPublicKey , postParameters ) ;
6769 Console . WriteLine ( "TOKEN VERIFICATION : " + tokenVerificationResult ) ;
6870 }
6971 catch ( Exception e )
7072 {
7173 Console . WriteLine ( "Exception on calling the API: " + e . Message ) ;
7274 }
7375 }
74-
75- public static bool Verify ( FlexPublicKey flexKey , IDictionary < string , string > postParameters )
76- {
77- var publicKeyStr = flexKey . der . publicKey ;
78- RSAParameters publicKey = DecodePublicKey ( Convert . FromBase64String ( publicKeyStr ) ) . ExportParameters ( false ) ;
79-
80- string signedFields = ( string ) postParameters [ "signedFields" ] ;
81- StringBuilder sb = new StringBuilder ( ) ;
82-
83- foreach ( string k in signedFields . Split ( ',' ) )
84- {
85- sb . Append ( ',' ) ;
86- sb . Append ( postParameters [ k ] ) ;
87- }
88-
89- if ( sb . Length > 0 )
90- {
91- sb . Remove ( 0 , 1 ) ;
92- }
93-
94- string signedValues = sb . ToString ( ) ;
95- string signature = ( string ) postParameters [ "signature" ] ;
96- return ValidateTokenSignature ( publicKey , signedValues , signature ) ;
97- }
98-
99- private static bool ValidateTokenSignature ( RSAParameters publicKey , string signedFields , string signature )
100- {
101- bool success = false ;
102-
103- using ( RSACryptoServiceProvider rsa = new RSACryptoServiceProvider ( ) )
104- {
105- byte [ ] bytesToVerify = Encoding . UTF8 . GetBytes ( signedFields ) ;
106- byte [ ] signedBytes = Convert . FromBase64String ( signature ) ;
107-
108- try
109- {
110- rsa . ImportParameters ( publicKey ) ;
111- success = rsa . VerifyData ( bytesToVerify , CryptoConfig . MapNameToOID ( "SHA512" ) , signedBytes ) ;
112- }
113- catch ( CryptographicException e )
114- {
115- throw new FlexSDKInternalException ( "Error validating signature" , e ) ;
116- }
117- catch ( System . Exception e )
118- {
119- throw new FlexSDKInternalException ( "Error validating signature" , e ) ;
120- }
121- finally
122- {
123- rsa . PersistKeyInCsp = false ;
124- }
125- }
126-
127- return success ;
128- }
129-
130- private static RSACryptoServiceProvider DecodePublicKey ( byte [ ] x509key )
131- {
132- // encoded OID sequence for PKCS #1 rsaEncryption szOID_RSA_RSA = "1.2.840.113549.1.1.1"
133- byte [ ] seqOID = { 0x30 , 0x0D , 0x06 , 0x09 , 0x2A , 0x86 , 0x48 , 0x86 , 0xF7 , 0x0D , 0x01 , 0x01 , 0x01 , 0x05 , 0x00 } ;
134- byte [ ] seq = new byte [ 15 ] ;
135-
136- // --------- Set up stream to read the asn.1 encoded SubjectPublicKeyInfo blob ------
137- MemoryStream mem = new MemoryStream ( x509key ) ;
138- BinaryReader binr = new BinaryReader ( mem ) ; // wrap Memory Stream with BinaryReader for easy reading
139- byte bt = 0 ;
140- ushort twobytes = 0 ;
141-
142- try
143- {
144- twobytes = binr . ReadUInt16 ( ) ;
145-
146- // data read as little endian order (actual data order for Sequence is 30 81)
147- if ( twobytes == 0x8130 )
148- {
149- binr . ReadByte ( ) ; // advance 1 byte
150- }
151- else if ( twobytes == 0x8230 )
152- {
153- binr . ReadInt16 ( ) ; // advance 2 bytes
154- }
155- else
156- {
157- return null ;
158- }
159-
160- seq = binr . ReadBytes ( 15 ) ; // read the Sequence OID
161-
162- // make sure Sequence for OID is correct
163- if ( ! CompareBytearrays ( seq , seqOID ) )
164- {
165- return null ;
166- }
167-
168- twobytes = binr . ReadUInt16 ( ) ;
169-
170- // data read as little endian order (actual data order for Bit String is 03 81)
171- if ( twobytes == 0x8103 )
172- {
173- binr . ReadByte ( ) ; // advance 1 byte
174- }
175- else if ( twobytes == 0x8203 )
176- {
177- binr . ReadInt16 ( ) ; // advance 2 bytes
178- }
179- else
180- {
181- return null ;
182- }
183-
184- bt = binr . ReadByte ( ) ;
185-
186- // expect null byte next
187- if ( bt != 0x00 )
188- {
189- return null ;
190- }
191-
192- twobytes = binr . ReadUInt16 ( ) ;
193-
194- // data read as little endian order (actual data order for Sequence is 30 81)
195- if ( twobytes == 0x8130 )
196- {
197- binr . ReadByte ( ) ; // advance 1 byte
198- }
199- else if ( twobytes == 0x8230 )
200- {
201- binr . ReadInt16 ( ) ; // advance 2 bytes
202- }
203- else
204- {
205- return null ;
206- }
207-
208- twobytes = binr . ReadUInt16 ( ) ;
209- byte lowbyte = 0x00 ;
210- byte highbyte = 0x00 ;
211-
212- // data read as little endian order (actual data order for Integer is 02 81)
213- if ( twobytes == 0x8102 )
214- {
215- lowbyte = binr . ReadByte ( ) ; // read next bytes which is bytes in modulus
216- }
217- else if ( twobytes == 0x8202 )
218- {
219- highbyte = binr . ReadByte ( ) ; // advance 2 bytes
220- lowbyte = binr . ReadByte ( ) ;
221- }
222- else
223- {
224- return null ;
225- }
226-
227- byte [ ] modint = { lowbyte , highbyte , 0x00 , 0x00 } ; // reverse byte order since asn.1 key uses big endian order
228- int modsize = BitConverter . ToInt32 ( modint , 0 ) ;
229-
230- byte firstbyte = binr . ReadByte ( ) ;
231- binr . BaseStream . Seek ( - 1 , SeekOrigin . Current ) ;
232-
233- if ( firstbyte == 0x00 )
234- {
235- // if first byte (highest order) of modulus is zero, don't include it
236- binr . ReadByte ( ) ; // skip this null byte
237- modsize -= 1 ; // reduce modulus buffer size by 1
238- }
239-
240- byte [ ] modulus = binr . ReadBytes ( modsize ) ; // read the modulus bytes
241-
242- // expect an Integer for the exponent data
243- if ( binr . ReadByte ( ) != 0x02 )
244- {
245- return null ;
246- }
247-
248- int expbytes = ( int ) binr . ReadByte ( ) ; // should only need one byte for actual exponent data (for all useful values)
249- byte [ ] exponent = binr . ReadBytes ( expbytes ) ;
250-
251- // ------- create RSACryptoServiceProvider instance and initialize with public key -----
252- RSACryptoServiceProvider rsa = new RSACryptoServiceProvider ( ) ;
253- RSAParameters rsaKeyInfo = new RSAParameters ( ) ;
254- rsaKeyInfo . Modulus = modulus ;
255- rsaKeyInfo . Exponent = exponent ;
256- rsa . ImportParameters ( rsaKeyInfo ) ;
257- return rsa ;
258- }
259- catch ( Exception )
260- {
261- return null ;
262- }
263- finally
264- {
265- binr . Close ( ) ;
266- }
267- }
268-
269- private static bool CompareBytearrays ( byte [ ] a , byte [ ] b )
270- {
271- if ( a . Length != b . Length )
272- {
273- return false ;
274- }
275-
276- int i = 0 ;
277- foreach ( byte c in a )
278- {
279- if ( c != b [ i ] )
280- {
281- return false ;
282- }
283-
284- i ++ ;
285- }
286-
287- return true ;
288- }
28976 }
29077}
0 commit comments