我正在查看此集成文档:
https://register.apple.com/resources/business-chat/BC_Sending_an_Auth_Msg.pdf
请参阅“如何解密身份验证令牌”部分
我用的是c#的弹力城堡1.8.3版
我有一个测试控制台应用:
namespace AppleBusinessChat45
{
class Program
{
static void Main(string[] args)
{
var publicKey = "BNY+I93aHVkXnNWKVLdrMJLXpQ1BsyHYoiv6UNi4rDUsRx3sNNhW8FNy9yUwxYprAwwfj1ZkoJ61Fs+SwjIbGPtXi52arvSbPglyBN4uAxtP3VP3LCP4JtSEjdgsgsretA==";
var privateKey = "pX/BvdXXUdpC79mW/jWi10Z6PJb5SBY2+aqkR/qYOjqgakKsqZFKnl0kz10Ve+BP";
var token = "BDiRKNnPiPUb5oala31nkmCaXMB0iyWy3Q93p6fN7vPxEQSUlFVsInkJzPBBqmW1FUIY1KBA3BQb3W3Qv4akZ8kblqbmvupE/EJzPKbROZFBNvxpvVOHHgO2qadmHAjHSmnxUuxrpKxopWnOgyhzUx+mBUTao0pcEgqZFw0Y/qZIJPf1KusCMlz5TAhpjsw=";
var decodedToken = Base64.Decode(token);
var decodedEphemeralPublicKey = decodedToken.Take(97).ToArray();
var encodedEphemeralPublicKeyCheck = Encoding.ASCII.GetString(Base64.Encode(decodedEphemeralPublicKey));
if (encodedEphemeralPublicKeyCheck != "BDiRKNnPiPUb5oala31nkmCaXMB0iyWy3Q93p6fN7vPxEQSUlFVsInkJzPBBqmW1FUIY1KBA3BQb3W3Qv4akZ8kblqbmvupE/EJzPKbROZFBNvxpvVOHHgO2qadmHAjHSg==")
throw new Exception("Public key check failed");
X9ECParameters curveParams = ECNamedCurveTable.GetByName("secp384r1");
ECPoint decodePoint = curveParams.Curve.DecodePoint(decodedEphemeralPublicKey);
ECDomainParameters domainParams = new ECDomainParameters(curveParams.Curve, curveParams.G, curveParams.N, curveParams.H, curveParams.GetSeed());
ECPublicKeyParameters ecPublicKeyParameters = new ECPublicKeyParameters(decodePoint, domainParams);
var x = ecPublicKeyParameters.Q.AffineXCoord.ToBigInteger();
var y = ecPublicKeyParameters.Q.AffineYCoord.ToBigInteger();
if (!x.Equals(new BigInteger("8706462696031173094919866327685737145866436939551712382591956952075131891462487598200779332295613073905587629438229")))
throw new Exception("X coord check failed");
if (!y.Equals(new BigInteger("10173258529327482491525749925661342501140613951412040971418641469645769857676705559747557238888921287857458976966474")))
throw new Exception("Y coord check failed");
var privateKeyBytes = Strings.ToByteArray(privateKey);
ECPrivateKeyParameters ecPrivateKeyParameters = new ECPrivateKeyParameters(new BigInteger(privateKeyBytes), domainParams);
IBasicAgreement agree = AgreementUtilities.GetBasicAgreement("ECDHC");
agree.Init(ecPrivateKeyParameters);
BigInteger sharedKey = agree.CalculateAgreement(ecPublicKeyParameters);
var sharedKeyBytes = sharedKey.ToByteArrayUnsigned();
// Expecting:
// 2lvSJsBO2keUHRfvPG6C1RMUmGpuDbdgNrZ9YD7RYnvAcfgq/fjeYr1p0hWABeif
Console.WriteLine("Done");
Console.ReadLine();
}
}
}
文档说明“示例私钥表示为转换为字节的无符号标量。”并且具有以下值:
pX/BvdXXUdpC79mW/jWi10Z6PJb5SBY2 aqkR/qYOjqgakKsqZFKnl0kz10Ve BP
我可能读错了私钥?因为我尝试解析的私钥与留档中的预期值不匹配。
网上几乎没有实现细节。
就Bouncy Castle而言,如何从字符串中读取私钥,然后用于生成共享密钥?
更新
对于那些寻找解密apple chat身份验证令牌的完整示例实现的人,请参阅下面:
namespace AppleBusinessChat45
{
class Program
{
static void Main(string[] args)
{
var privateKey = "pX/BvdXXUdpC79mW/jWi10Z6PJb5SBY2+aqkR/qYOjqgakKsqZFKnl0kz10Ve+BP";
var token = "BDiRKNnPiPUb5oala31nkmCaXMB0iyWy3Q93p6fN7vPxEQSUlFVsInkJzPBBqmW1FUIY1KBA3BQb3W3Qv4akZ8kblqbmvupE/EJzPKbROZFBNvxpvVOHHgO2qadmHAjHSmnxUuxrpKxopWnOgyhzUx+mBUTao0pcEgqZFw0Y/qZIJPf1KusCMlz5TAhpjsw=";
// #####
// ##### Step 1
// #####
var decodedToken = Convert.FromBase64String(token);
var decodedEphemeralPublicKey = decodedToken.Take(97).ToArray();
var encodedEphemeralPublicKeyCheck = Convert.ToBase64String(decodedEphemeralPublicKey);
if (encodedEphemeralPublicKeyCheck != "BDiRKNnPiPUb5oala31nkmCaXMB0iyWy3Q93p6fN7vPxEQSUlFVsInkJzPBBqmW1FUIY1KBA3BQb3W3Qv4akZ8kblqbmvupE/EJzPKbROZFBNvxpvVOHHgO2qadmHAjHSg==")
throw new Exception("Public key check failed");
X9ECParameters curveParams = ECNamedCurveTable.GetByName("secp384r1");
ECPoint decodePoint = curveParams.Curve.DecodePoint(decodedEphemeralPublicKey);
ECDomainParameters domainParams = new ECDomainParameters(curveParams.Curve, curveParams.G, curveParams.N, curveParams.H, curveParams.GetSeed());
ECPublicKeyParameters ecPublicKeyParameters = new ECPublicKeyParameters(decodePoint, domainParams);
var x = ecPublicKeyParameters.Q.AffineXCoord.ToBigInteger();
var y = ecPublicKeyParameters.Q.AffineYCoord.ToBigInteger();
if (!x.Equals(new BigInteger("8706462696031173094919866327685737145866436939551712382591956952075131891462487598200779332295613073905587629438229")))
throw new Exception("X coord check failed");
if (!y.Equals(new BigInteger("10173258529327482491525749925661342501140613951412040971418641469645769857676705559747557238888921287857458976966474")))
throw new Exception("Y coord check failed");
Console.WriteLine("Step 1 complete");
// #####
// ##### Step 2
// #####
var privateKeyBytes = Convert.FromBase64String(privateKey);
var ecPrivateKeyParameters = new ECPrivateKeyParameters("ECDHC", new BigInteger(1, privateKeyBytes), domainParams);
var privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(ecPrivateKeyParameters);
var ecPrivateKey = (ECPrivateKeyParameters) PrivateKeyFactory.CreateKey(privateKeyInfo);
IBasicAgreement agree = AgreementUtilities.GetBasicAgreement("ECDHC");
agree.Init(ecPrivateKey);
BigInteger sharedKey = agree.CalculateAgreement(ecPublicKeyParameters);
var sharedKeyBytes = sharedKey.ToByteArrayUnsigned();
var sharedKeyBase64 = Convert.ToBase64String(sharedKeyBytes);
if (sharedKeyBase64 != "2lvSJsBO2keUHRfvPG6C1RMUmGpuDbdgNrZ9YD7RYnvAcfgq/fjeYr1p0hWABeif")
throw new Exception("Shared key check failed");
Console.WriteLine("Step 2 complete");
// #####
// ##### Step 3
// #####
var kdf2Bytes = Kdf2(sharedKeyBytes, decodedEphemeralPublicKey);
var kdf2Base64 = Convert.ToBase64String(kdf2Bytes);
if (kdf2Base64 != "mAzkYatDlz4SzrCyM23NhgL/+mE3eGgfUz9h1CFPhZOtXequzN3Q8w+B5GE2eU5g")
throw new Exception("Kdf2 failed");
Console.WriteLine("Step 3 complete");
// #####
// ##### Step 4
// #####
var decryptionKeyBytes = kdf2Bytes.Take(32).ToArray();
var decryptionIvBytes = kdf2Bytes.Skip(32).ToArray();
var decryptionKeyBase64 = Convert.ToBase64String(decryptionKeyBytes);
var decryptionIvBase64 = Convert.ToBase64String(decryptionIvBytes);
if (decryptionKeyBase64 != "mAzkYatDlz4SzrCyM23NhgL/+mE3eGgfUz9h1CFPhZM=")
throw new Exception("Decryption key check failed");
if (decryptionIvBase64 != "rV3qrszd0PMPgeRhNnlOYA==")
throw new Exception("Decryption iv check failed");
var encryptedDataBytes = decodedToken.Skip(97).Take(decodedToken.Length - 113).ToArray();
var tagBytes = decodedToken.Skip(decodedToken.Length - 16).ToArray();
var encryptedDataBase64 = Convert.ToBase64String(encryptedDataBytes);
var tagBase64 = Convert.ToBase64String(tagBytes);
if (encryptedDataBase64 != "afFS7GukrGilac6DKHNTH6YFRNqjSlwSCpkXDRj+")
throw new Exception("Encrypted data check failed");
if (tagBase64 != "pkgk9/Uq6wIyXPlMCGmOzA==")
throw new Exception("Tag check failed");
KeyParameter keyParam = ParameterUtilities.CreateKeyParameter("AES", decryptionKeyBytes);
ParametersWithIV parameters = new ParametersWithIV(keyParam, decryptionIvBytes);
IBufferedCipher cipher = CipherUtilities.GetCipher("AES/GCM/NoPadding");
cipher.Init(false, parameters);
var resultBytes = cipher.DoFinal(encryptedDataBytes.Concat(tagBytes).ToArray());
var resultBase64 = Convert.ToBase64String(resultBytes);
var resultString = Strings.FromByteArray(resultBytes);
if (resultString != "xXTi32iZwrQ6O8Sy6r1isKwF6Ff1Py")
throw new Exception("Decryption failed");
Console.WriteLine("Step 4 complete");
Console.WriteLine(resultString);
Console.WriteLine();
Console.WriteLine("Done... press any key to finish");
Console.ReadLine();
}
static byte[] Kdf2(byte[] sharedKeyBytes, byte[] ephemeralKeyBytes)
{
var gen = new Kdf2BytesGenerator(new Sha256Digest());
gen.Init(new KdfParameters(sharedKeyBytes, ephemeralKeyBytes));
byte[] encryptionKeyBytes = new byte[48];
gen.GenerateBytes(encryptionKeyBytes, 0, encryptionKeyBytes.Length);
return encryptionKeyBytes;
}
}
}
替换为:
var privateKeyBytes = Strings.ToByteArray(privateKey);
ECPrivateKeyParameters ecPrivateKeyParameters = new ECPrivateKeyParameters(new BigInteger(privateKeyBytes), domainParams);
IBasicAgreement agree = AgreementUtilities.GetBasicAgreement("ECDHC");
agree.Init(ecPrivateKeyParameters);
有了这个:
var privateKeyBytes = Convert.FromBase64String(privateKey);
var ecPrivateKeyParameters = new ECPrivateKeyParameters("ECDHC", new BigInteger(1, privateKeyBytes), domainParams);
var privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(ecPrivateKeyParameters);
var ecPrivateKey = (ECPrivateKeyParameters)PrivateKeyFactory.CreateKey(privateKeyInfo);
var agree = AgreementUtilities.GetBasicAgreement("ECDHC");
agree.Init(ecPrivateKey);
它应该有效。
我正在阅读apple business chat api文档,我在“接收大型交互式数据有效载荷”部分。最后一步是解密附件,然后发送到业务聊天Api。 下载 ---和破译说明文档-- 然后,使用密码库,使用AES/CTR/NoPadding算法对文件进行解密,并使用下载附件的附件字典中的密钥值,使用全零16字节初始化向量(IV)。 因此,以下是我对本文档的解释,因为它们使我几乎没有什么可处理的。 这
我有一个LaravelAPI(实际上是LumenAPI)服务于VueJS前端。Vue应用程序允许用户登录到谷歌。然后将Google令牌发送回Lumen API,后者使用Google验证令牌,然后验证电子邮件地址是否为有效用户。然后它生成一个令牌,与用户一起存储在数据库中,并返回用户对象。 我没有使用Passport或jwt auth之类的东西。那么现在,我如何使用默认的Auth中间件来验证(现在已
在我的Jitsi Meet Prodody配置文件中:~/。jitsi meet cfg/prosody/config/conf.d 我有以下配置: 有了它,我可以通过令牌进行身份验证。 但是,如果我不指定任何令牌,例如: https://jitsi.mydummyserver.com/test 然后我得到以下提示询问用户和密码: 有没有办法只允许令牌身份验证并完全摆脱那个提示? 谢谢
null
我刚刚开始在.NET中开发我的第一个REST API。由于它将是无状态的,我将使用令牌进行身份验证: 基本思想(System.Security.Cryptography): null 检查凭据是否有效(用户名,将哈希密码与db值进行比较) 如果为真,则加密数据对象 对生成的令牌使用HMAC,并将其存储到数据库 将令牌(不带HMAC)返回给用户(cookie/字符串) 对需要身份验证的方法的请求:
我尝试从PHP向Android手机应用发送推送通知 我使用谷歌云消息,但在浏览器中我看到错误: 请求缺少身份验证密钥(FCM令牌)。请参阅FCM文档的“认证”部分,网址为https://firebase.google.com/docs/cloud-messaging/server.错误401 此外,我可以从c#控制台应用程序发送消息推送并在我的手机上接收它(我认为,授权密钥是正确的): 问题:如何