在 Classic 中验证 Stripe Webhook 签名 ASP
Validating Stripe Webhook Signatures in Classic ASP
Stripe 建议使用他们的库来验证签名,但由于他们没有适用于 Classic 的库,我必须手动完成,我真的很费力。
(https://stripe.com/docs/webhooks/signatures#verify-manually)
Step 1: Extract the timestamp and signatures from the header Split the
header, using the , character as the separator, to get a list of
elements. Then split each element, using the = character as the
separator, to get a prefix and value pair. The value for the prefix t
corresponds to the timestamp, and v1 corresponds to the signature(s).
You can discard all other elements.
Step 2: Prepare the signed_payload string You achieve this by
concatenating: The timestamp (as a string) The character . The actual
JSON payload (i.e., the request’s body)
Step 3: Determine the expected signature Compute an HMAC with the
SHA256 hash function. Use the endpoint’s signing secret as the key,
and use the signed_payload string as the message.
Step 4: Compare signatures Compare the signature(s) in the header to
the expected signature. If a signature matches, compute the difference
between the current timestamp and the received timestamp, then decide
if the difference is within your tolerance.To protect against timing
attacks, use a constant-time string comparison to compare the expected
signature to each of the received signatures.
我认为我使用以下代码是正确的:
'Keys
If strStripeMode = "live" Then
strSigningSecret = ""
Else
strSigningSecret = "whsec_CIXV2............................UR8Ta0"
End if
'1. Payload
lngBytesCount = Request.TotalBytes
strPayload = BytesToStr(Request.BinaryRead(lngBytesCount))
'2. Stripe-Signature
strStripeSignature = Request.ServerVariables("HTTP_STRIPE_SIGNATURE")
arrStripeSignature = Split(strStripeSignature,",")
intTimeStamp = REPLACE(arrStripeSignature(0),"t=","")
strV1Signature = REPLACE(arrStripeSignature(1),"v1=","")
strSignedPayload = intTimeStamp & "." & strV1Signature & strPayload
'3. Hash using 'signing secret' as the key.
set crypt = Server.CreateObject("Chilkat_9_5_0.Crypt2")
crypt.HashAlgorithm = "sha256"
crypt.EncodingMode = "hex"
crypt.SetHmacKeyEncoded strSigningSecret,"ascii"
strHashedSignature = crypt.HmacStringENC(strSignedPayload)
set crypt = nothing
'4. Compare the values
If strHashedSignature = strV1Signature Then
'Valid
Response.Status = "200"
Response.Write(Response.Status)
'------------ DO SOMETHING------------
Response.End
Else
'Invalid
Response.Status = "300"
Response.Write(Response.Status)
'------------ DO SOMETHING------------
Response.End
End if
' Bytes to String Function
Function BytesToStr(bytes)
Dim Stream
Set Stream = Server.CreateObject("Adodb.Stream")
Stream.Type = 1 'adTypeBinary
Stream.Open
Stream.Write bytes
Stream.Position = 0
Stream.Type = 2 'adTypeText
Stream.Charset = "iso-8859-1"
BytesToStr = Stream.ReadText
Stream.Close
Set Stream = Nothing
End Function
我遇到的第一个问题是我不确定我是否在第 2 步中正确生成了 signed_payload 字符串。第二个问题是步骤 #3 中的 strHashedSignature 显示为空白,可能是由于未正确生成 signed_payload 字符串 (strSignedPayload)。
我想我应该更新这个以防其他人在 future.The 解决方案中遇到问题是双重的。
首先是我在 signed_payload 字符串上完全隔开,包括出于某种原因的 v1Signature(我借口是周五一天结束 :)
strSignedPayload = intTimeStamp & "." & strV1Signature & strPayload
它应该只是:
strSignedPayload = intTimeStamp & "." & strPayload
第二个如@karllekko 所述,编码需要为 UTF-8
Stripe 建议使用他们的库来验证签名,但由于他们没有适用于 Classic 的库,我必须手动完成,我真的很费力。
(https://stripe.com/docs/webhooks/signatures#verify-manually)
Step 1: Extract the timestamp and signatures from the header Split the header, using the , character as the separator, to get a list of elements. Then split each element, using the = character as the separator, to get a prefix and value pair. The value for the prefix t corresponds to the timestamp, and v1 corresponds to the signature(s). You can discard all other elements.
Step 2: Prepare the signed_payload string You achieve this by concatenating: The timestamp (as a string) The character . The actual JSON payload (i.e., the request’s body)
Step 3: Determine the expected signature Compute an HMAC with the SHA256 hash function. Use the endpoint’s signing secret as the key, and use the signed_payload string as the message.
Step 4: Compare signatures Compare the signature(s) in the header to the expected signature. If a signature matches, compute the difference between the current timestamp and the received timestamp, then decide if the difference is within your tolerance.To protect against timing attacks, use a constant-time string comparison to compare the expected signature to each of the received signatures.
我认为我使用以下代码是正确的:
'Keys
If strStripeMode = "live" Then
strSigningSecret = ""
Else
strSigningSecret = "whsec_CIXV2............................UR8Ta0"
End if
'1. Payload
lngBytesCount = Request.TotalBytes
strPayload = BytesToStr(Request.BinaryRead(lngBytesCount))
'2. Stripe-Signature
strStripeSignature = Request.ServerVariables("HTTP_STRIPE_SIGNATURE")
arrStripeSignature = Split(strStripeSignature,",")
intTimeStamp = REPLACE(arrStripeSignature(0),"t=","")
strV1Signature = REPLACE(arrStripeSignature(1),"v1=","")
strSignedPayload = intTimeStamp & "." & strV1Signature & strPayload
'3. Hash using 'signing secret' as the key.
set crypt = Server.CreateObject("Chilkat_9_5_0.Crypt2")
crypt.HashAlgorithm = "sha256"
crypt.EncodingMode = "hex"
crypt.SetHmacKeyEncoded strSigningSecret,"ascii"
strHashedSignature = crypt.HmacStringENC(strSignedPayload)
set crypt = nothing
'4. Compare the values
If strHashedSignature = strV1Signature Then
'Valid
Response.Status = "200"
Response.Write(Response.Status)
'------------ DO SOMETHING------------
Response.End
Else
'Invalid
Response.Status = "300"
Response.Write(Response.Status)
'------------ DO SOMETHING------------
Response.End
End if
' Bytes to String Function
Function BytesToStr(bytes)
Dim Stream
Set Stream = Server.CreateObject("Adodb.Stream")
Stream.Type = 1 'adTypeBinary
Stream.Open
Stream.Write bytes
Stream.Position = 0
Stream.Type = 2 'adTypeText
Stream.Charset = "iso-8859-1"
BytesToStr = Stream.ReadText
Stream.Close
Set Stream = Nothing
End Function
我遇到的第一个问题是我不确定我是否在第 2 步中正确生成了 signed_payload 字符串。第二个问题是步骤 #3 中的 strHashedSignature 显示为空白,可能是由于未正确生成 signed_payload 字符串 (strSignedPayload)。
我想我应该更新这个以防其他人在 future.The 解决方案中遇到问题是双重的。
首先是我在 signed_payload 字符串上完全隔开,包括出于某种原因的 v1Signature(我借口是周五一天结束 :)
strSignedPayload = intTimeStamp & "." & strV1Signature & strPayload
它应该只是:
strSignedPayload = intTimeStamp & "." & strPayload
第二个如@karllekko 所述,编码需要为 UTF-8