1515using HomeKitDotNet . Models ;
1616using HomeKitDotNet . TLV ;
1717using HomeKitDotNet . TLV . Enums ;
18+ using System . Globalization ;
1819using System . Net ;
1920using System . Numerics ;
2021using System . Security . Cryptography ;
@@ -39,7 +40,7 @@ public Controller(out byte[] publicKey, out byte[] privateKey)
3940 {
4041 byte [ ] seed = RandomNumberGenerator . GetBytes ( 32 ) ;
4142 Ed25519 . KeyPairFromSeed ( out LTPK , out LTSK , seed ) ;
42- deviceID = RandomNumberGenerator . GetBytes ( 16 ) ;
43+ deviceID = Encoding . UTF8 . GetBytes ( Guid . NewGuid ( ) . ToString ( "D" , CultureInfo . InvariantCulture ) ) ;
4344 publicKey = LTPK ;
4445 privateKey = LTSK ;
4546 }
@@ -52,6 +53,12 @@ public Controller(out byte[] publicKey, out byte[] privateKey)
5253 /// <param name="deviceID"></param>
5354 public Controller ( byte [ ] privateKey , byte [ ] publicKey , byte [ ] deviceID )
5455 {
56+ if ( privateKey . Length != 64 )
57+ throw new ArgumentException ( "Invalid Private Key Length: " + privateKey . Length ) ;
58+ if ( publicKey . Length != 32 )
59+ throw new ArgumentException ( "Invalid Public Key Length: " + publicKey . Length ) ;
60+ if ( deviceID . Length != 36 )
61+ throw new ArgumentException ( "Invalid Device ID Length: " + deviceID . Length ) ;
5562 LTPK = publicKey ;
5663 LTSK = privateKey ;
5764 this . deviceID = deviceID ;
@@ -168,44 +175,48 @@ public async Task<bool> UnPair(HomeKitEndPoint endpoint)
168175 /// <param name="destination"></param>
169176 /// <returns></returns>
170177 /// <exception cref="IOException"></exception>
178+ /// <exception cref="UnauthorizedAccessException"></exception>
171179 public async Task < AccessoryInfo > Pair ( long setupPin , IPEndPoint destination )
172180 {
173181 string I = "Pair-Setup" ;
174182 string P = setupPin . ToString ( "000-00-000" ) ;
175183
176184 Connection con = new Connection ( destination ) ;
177185
178- Console . WriteLine ( "LTPK: " + BitConverter . ToString ( LTPK ) ) ;
179- Console . WriteLine ( "LTSK: " + BitConverter . ToString ( LTSK ) ) ;
180-
181186 //Step 1
182187 HttpResponseMessage msg = await con . Post ( "/pair-setup" , new TLVInt ( TLVType . kTLVType_State , ( byte ) PairingState . M1 ) , new TLVInt ( TLVType . kTLVType_Method , ( byte ) Method . PairSetupWithAuth ) ) ;
183188 if ( ! msg . IsSuccessStatusCode )
184- throw new IOException ( $ "Pair Step 1 Failed with { msg . StatusCode } : { msg . ReasonPhrase } ") ;
189+ throw new IOException ( $ "Pair Step 2 Failed with { msg . StatusCode } : { msg . ReasonPhrase } ") ;
185190 List < TLVValue > responseTLVs = TLVValue . CollectionFromStream ( msg . Content . ReadAsStream ( ) ) ;
186191
187192 //Step 3
188- byte [ ] bytes = TLVValue . Concat ( TLVType . kTLVType_PublicKey , responseTLVs ) ;
189- BigInteger B = new BigInteger ( bytes , true , true ) ;
193+ byte [ ] accessoryPK = TLVValue . Concat ( TLVType . kTLVType_PublicKey , responseTLVs ) ;
194+ if ( accessoryPK . Length == 0 )
195+ throw new IOException ( $ "Pair Step 3 Failed - Public key is missing") ;
196+ if ( responseTLVs . Any ( t => t . Type == TLVType . kTLVType_Error ) )
197+ throw new IOException ( "Received M2 Error" ) ;
198+ BigInteger B = new BigInteger ( accessoryPK , true , true ) ;
190199 byte [ ] s = ( responseTLVs . Find ( t => t . Type == TLVType . kTLVType_Salt ) as TLVBytes ) ! . Value ;
191200 SRP srp = new SRP ( ) ;
192201 BigInteger A = srp . GenerateAValues ( ) ;
193202 BigInteger K = srp . ComputeSessionKey ( I , P , s , B ) ;
194203 BigInteger M1 = srp . GenerateClientProof ( I , s , A , B , K ) ;
195- msg = await con . Post ( "/pair-setup" , [
204+ msg = await con . Post ( "/pair-setup" ,
196205 new TLVInt ( TLVType . kTLVType_State , ( byte ) PairingState . M3 ) ,
197206 new TLVBytes ( TLVType . kTLVType_PublicKey , A . ToByteArray ( true , true ) ) ,
198207 new TLVBytes ( TLVType . kTLVType_Proof , M1 . ToByteArray ( true , true ) )
199- ] ) ;
208+ ) ;
200209
201210 if ( ! msg . IsSuccessStatusCode )
202211 {
203212 string content = new StreamReader ( msg . Content . ReadAsStream ( ) ) . ReadToEnd ( ) ;
204- throw new IOException ( $ "Pair Step 3 Failed with { msg . StatusCode } : { msg . ReasonPhrase } : { content } ") ;
213+ throw new IOException ( $ "Pair Step 4 Failed with { msg . StatusCode } : { msg . ReasonPhrase } : { content } ") ;
205214 }
206215
207216 //Step 5
208217 responseTLVs = TLVValue . CollectionFromStream ( msg . Content . ReadAsStream ( ) ) ;
218+ if ( responseTLVs . Any ( t => t . Type == TLVType . kTLVType_Error ) )
219+ throw new UnauthorizedAccessException ( "Invalid PIN Code" ) ;
209220 BigInteger M2 = new BigInteger ( ( responseTLVs . Find ( t => t . Type == TLVType . kTLVType_Proof ) as TLVBytes ) ! . Value , true , true ) ;
210221 bool valid = srp . ValidateServerProof ( M2 , M1 , K ) ;
211222
@@ -229,10 +240,10 @@ public async Task<AccessoryInfo> Pair(long setupPin, IPEndPoint destination)
229240 encrypter . Encrypt ( Encoding . ASCII . GetBytes ( "\0 \0 \0 \0 PS-Msg05" ) , encryptionPayload . ToArray ( ) , encryptedPayload . AsSpan ( ) . Slice ( 0 , ( int ) encryptionPayload . Length ) , encryptedPayload . AsSpan ( ) . Slice ( ( int ) encryptionPayload . Length , 16 ) ) ;
230241 }
231242
232- msg = await con . Post ( "/pair-setup" , [
243+ msg = await con . Post ( "/pair-setup" ,
233244 new TLVInt ( TLVType . kTLVType_State , ( byte ) PairingState . M5 ) ,
234245 new TLVBytes ( TLVType . kTLVType_EncryptedData , encryptedPayload )
235- ] ) ;
246+ ) ;
236247
237248 if ( ! msg . IsSuccessStatusCode )
238249 {
0 commit comments