Skip to main content
Version: 1.0

1.2 Verification Result

Verification Result

After a successful verification, VerifySpeed provides an encrypted token that contains the verification details. This token must be decrypted on your server using your server key to extract the verified phone number and other information.

Token Structure

The verification token contains three pieces of information separated by the | character:

phoneNumber|dateOfVerified|usedMethodName

Components:

  • phoneNumber: The verified phone number
  • dateOfVerified: The date and time when verification was completed
  • usedMethodName: The verification method that was used (e.g., "WhatsApp Message", "Telegram OTP", "SMS OTP")

Token Encryption

VerifySpeed encrypts the token using AES-256 encryption with the following process:

  1. Payload Creation: Combines the three components with | separator
  2. Key Derivation: Uses SHA256 hash of your server key as the AES key
  3. Encryption: Applies AES-256 encryption with a random IV
  4. Encoding: Returns the result as a Base64-encoded string

Decrypting the Token

You must decrypt the token on your server using your server key to access the verification details. We provide official packages for each programming language that contain the decryption tools:

Package Installation:

dotnet add package VerifySpeed.VSCSharp --version 1.0.15

Usage:

using VerifySpeed.VSCSharp;

// Decrypt the verification token
var result = token.DecryptVerificationToken(serverKey);
Console.WriteLine($"Phone: {result.PhoneNumber}");

Manual Implementation

If you prefer to implement the decryption manually or need to customize the behavior, here are the complete code examples:

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

public static class EncryptionTool
{
/// <summary>
/// Decrypts an encrypted verification token using the specified server key
/// and returns the corresponding VerificationResult object.
/// </summary>
/// <param name="token">The Base64-encoded encrypted token string to decrypt.</param>
/// <param name="serverKey">The server key used for AES decryption.</param>
/// <returns>A VerificationResult object representing the decrypted token.</returns>
public static VerificationResult DecryptVerificationToken(this string token, string serverKey)
{
if (string.IsNullOrWhiteSpace(token))
{
throw new ArgumentException("The verification token cannot be null or empty");
}

string decrypted = Decrypt(token, serverKey);
string[] parts = decrypted.Split('|');

if (parts.Length != 3)
{
throw new ArgumentException("The token format is invalid or corrupted");
}

string phoneNumber = parts[0];
DateTime dateOfVerification = DateTime.Parse(parts[1]);
string methodName = parts[2];

return new VerificationResult
{
PhoneNumber = phoneNumber,
DateOfVerification = dateOfVerification,
MethodName = methodName
};
}

private static string Decrypt(string token, string serverKey)
{
try
{
byte[] cipherBytes = Convert.FromBase64String(token);
using var aes = Aes.Create();
aes.Key = SHA256.HashData(Encoding.UTF8.GetBytes(serverKey));

using var memoryStream = new MemoryStream(cipherBytes);
var iv = new byte[aes.BlockSize / 8];
_ = memoryStream.Read(iv);
aes.IV = iv;

using var cryptoStream = new CryptoStream(
memoryStream,
aes.CreateDecryptor(),
CryptoStreamMode.Read
);
using var streamReader = new StreamReader(cryptoStream);
return streamReader.ReadToEnd();
}
catch (Exception ex)
{
throw new Exception("Failed to decrypt the verification token", ex);
}
}
}

public class VerificationResult
{
public string PhoneNumber { get; set; }
public DateTime DateOfVerification { get; set; }
public string MethodName { get; set; }
}

Security Considerations

  • Server Key Protection: Keep your server key secure and never expose it in client-side code
  • Token Validation: Always validate the decrypted data before using it in your application
  • Error Handling: Implement proper error handling for decryption failures
  • Token Expiry: Consider implementing token expiry validation based on the verification date

Integration Flow

  1. Client Side: User completes verification and receives encrypted token
  2. Client to Server: Send encrypted token to your backend
  3. Server Decryption: Decrypt token using your server key
  4. Data Extraction: Extract phone number and verification details
  5. Application Logic: Use the verified phone number in your application

Error Handling

Common errors you may encounter:

  • Invalid Token Format: Token is corrupted or malformed
  • Decryption Failure: Server key mismatch or token corruption
  • Missing Data: Required token components are missing
  • Invalid Date: Verification date cannot be parsed
  • Token Expired: Token verification date is too old (recommended: reject tokens older than 5 minutes)

Always implement proper error handling to gracefully manage these scenarios in your application.

Token Expiry Validation

Security Recommendation: Never accept verification tokens where the date of verification is more than 5 minutes old. This prevents replay attacks and ensures the verification is recent and valid.

Here's an example of how to implement token expiry validation:

public static VerificationResult DecryptVerificationToken(this string token, string serverKey, int maxAgeMinutes = 5)
{
// ... existing decryption code ...

var result = new VerificationResult
{
PhoneNumber = phoneNumber,
DateOfVerification = dateOfVerification,
MethodName = methodName
};

// Validate token age
var tokenAge = DateTime.UtcNow - dateOfVerification;
if (tokenAge.TotalMinutes > maxAgeMinutes)
{
throw new ArgumentException($"Token is too old. Age: {tokenAge.TotalMinutes:F1} minutes, Maximum allowed: {maxAgeMinutes} minutes");
}

return result;
}