- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
作为此问题的后续:Implementing WS-Security in Progress ABL ,我将继续努力在 Progress OpenEdge 中实现 WS-Security。
我的问题:
针对特定 Web 服务的每个请求,我都会根据以下内容生成密码摘要:
然后将随机数、时间戳和摘要添加到 Web 服务调用的 Soap header 中。
这在大多数情况下工作正常,但在 100 个请求中大约有 5 个会失败(请参阅下面的更多信息)。
这就是我生成摘要的方式:
PROCEDURE generatePassHashNonceClear:
/*------------------------------------------------------------------------------
Purpose:
Generates a password hash for WS-Security
General algorithm:
Digest = base64(sha1(Nonce + Timestamp + sha1(Pwd)))
------------------------------------------------------------------------------*/
DEFINE INPUT PARAMETER pcNonce AS CHARACTER NO-UNDO.
DEFINE INPUT PARAMETER pcCreated AS CHARACTER NO-UNDO.
DEFINE INPUT PARAMETER pcPassword AS CHARACTER NO-UNDO.
DEFINE OUTPUT PARAMETER pcHash AS CHARACTER NO-UNDO.
DEFINE VARIABLE mBytes AS MEMPTR NO-UNDO.
DEFINE VARIABLE mSHA1 AS MEMPTR NO-UNDO.
/*
Set size of mempointer, add 20 since we are adding the 20 byte
SHA1-DIGEST of the clear password in the end.
*/
SET-SIZE(mBytes) = LENGTH(pcNonce) + LENGTH(pcCreated) + 20.
/* Put the decoded nonce first */
PUT-STRING(mBytes, 1) = pcNonce.
/* Add create time */
PUT-STRING(mBytes, 1 + LENGTH(pcNonce)) = pcCreated.
/* Set SHA1 returns a 20 byte raw string. */
SET-SIZE(mSHA1) = 20.
mSHA1 = SHA1-DIGEST(pcPassword).
/* Add password, SHA1-digested (so we need to put bytes instead of a string */
PUT-BYTES(mBytes, 1 + LENGTH(pcNonce) + LENGTH(pcCreated)) = mSHA1.
/* Create out-data in B64-encoded format */
pcHash = STRING(BASE64-ENCODE(SHA1-DIGEST(mBytes))).
/* Clean up mempointers */
SET-SIZE(mBytes) = 0.
SET-SIZE(mSHA1) = 0.
END PROCEDURE.
该过程的调用方式如下:
DEFINE VARIABLE cPasswordClear AS CHARACTER NO-UNDO.
DEFINE VARIABLE dtZuluNow AS DATETIME NO-UNDO.
DEFINE VARIABLE cCreated AS CHARACTER NO-UNDO.
DEFINE VARIABLE cNonceB64 AS CHARACTER NO-UNDO.
DEFINE VARIABLE cNonce AS CHARACTER NO-UNDO.
DEFINE VARIABLE cPasswordDigest AS CHARACTER NO-UNDO.
/*
Get time in UTC/GMT/ZULU/Timezone 0 and store
it with 000 as milliseconds + Z for timezone Zulu
Nonce is a random generated string
*/
ASSIGN
dtZuluNow = DATETIME-TZ(NOW,0)
cCreated = STRING(dtZuluNow, "9999-99-99THH:MM:SS") + ":000Z"
cPasswordClear = "SECRET"
cNonceB64 = BASE64-ENCODE(GENERATE-RANDOM-KEY)
cNonce = STRING(BASE64-DECODE(cNonceB64)).
RUN generatePassHashNonceClear( cNonce, cCreated, cPasswordClear, OUTPUT cPasswordDigest).
我所知道的:
这对于 10 000 个请求中的 9 500 个请求来说效果很好。但失败率是5%。不幸的是,错误消息没有帮助,所以我真正能看到的是登录失败。 Web 服务提供商表示,由于摘要不正确,登录被拒绝。
我做了什么:
为了测试我的摘要程序,我创建了一个小型 python 程序。当我尝试使用失败登录的数据(随机数和时间戳)时,这确实会创建不同的摘要。然而,我不是一个 Python 程序员,所以这个程序很可能有问题(但它也应该在 95% 的所有情况下都工作,这将是一个非常奇怪的巧合)。
这是Python程序:
import hashlib
def createDigest(Nonce, Created, Password):
"This function returns a digest"
NonceB64 = Nonce.decode("base64","strict")
pdgst = hashlib.sha1()
pdgst.update(Password)
PasswordDgst = pdgst.digest()
FinalDgst = hashlib.sha1()
FinalDgst.update(NonceB64)
FinalDgst.update(Created)
FinalDgst.update(PasswordDgst)
FinalTxt = FinalDgst.digest().encode("base64","strict")
print "Final digest : " + FinalTxt
return
print "This digest is repeated in Progress OpenEdge"
createDigest("tGxF8+DAmJvQo93PNZt5Nw==", "2015-04-08T20:10:44:000Z", "SECRET")
print "This digest isn't repeated in Progress OpenEdge"
createDigest("XdcAW1TdTr+MLp4t0QkJ8g==", "2015-04-08T20:10:44:000Z", "SECRET")
我的真实密码当然不是“ secret ”,这让我相信错误与随机数有关。将密码更改为“SECRET”会使摘要有所不同,但随后 Progress 和 Python 摘要之间的差异仍然存在(上面的第一个示例在更改之前和之后生成了类似的摘要,但第二个示例没有)。
我有一个与 Progress Support 合作的开放案例,但他们似乎和我一样为此苦苦挣扎。
我已在 RHEL 和 Windows 7 上的 OpenEdge 11.3.1 和 11.4 中对此进行了测试,行为保持不变。
最佳答案
回答我自己的问题以供将来引用:
正如 @TomBascom 指出的那样,该问题与代码页转换有关,但实际错误实际上在“链”中早于 SHA 消化。
cNonceB64 = BASE64-ENCODE(GENERATE-RANDOM-KEY)
cNonce = STRING(BASE64-DECODE(cNonceB64))
在第二行中,只要生成的 key 包含 iso8859-1 和 UTF-8 之间不匹配的值,cNonce 的值就会被破坏。
简单的解决方案是将 cNonce 变量更改为 mempointer,然后重写生成摘要的过程。
/* Optimistic, should really be based on current symmetric encryption algorithm */
SET-SIZE(mNonce) = 16.
ASSIGN
mNonce = GENERATE-RANDOM-KEY
cNonceB64 = BASE64-ENCODE(mNonce).
然后是生成密码摘要的新过程:
PROCEDURE generateDigest:
/*------------------------------------------------------------------------------
Purpose: Generates a password hash for WS-Security
Parameters: <none>
Notes:
------------------------------------------------------------------------------*/
DEFINE INPUT PARAMETER mNonce AS MEMPTR NO-UNDO.
DEFINE INPUT PARAMETER pcCreated AS CHARACTER NO-UNDO.
DEFINE INPUT PARAMETER pcPassword AS CHARACTER NO-UNDO.
DEFINE OUTPUT PARAMETER pcHash AS CHARACTER NO-UNDO.
DEFINE VARIABLE mBytes AS MEMPTR NO-UNDO.
DEFINE VARIABLE mSHA1 AS MEMPTR NO-UNDO.
/*
Set size of mempointer, add 20 since we are adding the 20 byte
SHA1-DIGEST of the clear password in the end.
*/
SET-SIZE(mBytes) = LENGTH(pcCreated) + 36. /* 16 + 20 = 36 */
/* Put the decoded nonce first */
PUT-BYTES(mBytes, 1) = mNonce.
/* Add create time */
PUT-STRING(mBytes, 17) = pcCreated. /* 16 + 1 = 17 */
/* Set SHA1 returns a 20 byte raw string. */
SET-SIZE(mSHA1) = 20.
mSHA1 = SHA1-DIGEST(pcPassword).
/* Add password, SHA1-digested (so we need to put bytes instead of a string */
PUT-BYTES(mBytes, 17 + LENGTH(pcCreated)) = mSHA1. /* 16 + 1 = 17 */
/* Create out-data in B64-encoded format */
pcHash = STRING(BASE64-ENCODE(SHA1-DIGEST(mBytes))).
/* Clean up mempointers */
SET-SIZE(mBytes) = 0.
SET-SIZE(mSHA1) = 0.
SET-SIZE(mNonce) = 0.
END PROCEDURE.
关于python - OpenEdge 中的 WS-Security(续),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29918612/
当我的测试用例挂起时,我设法生成了线程转储。但是,这似乎不是死锁、竞争条件或资源争用。但是在我的加载测试工具中使用 3 个虚拟用户运行测试用例时,它肯定会挂起。任何人都可以在这里指出我正确的方向吗?干
复制代码 代码如下: #!/usr/bin/perl use File::DirWalk; use File::Basename; use Data::Dumper; use warnings;
个人认为影响的原因: 匹配到的图片url并不是有效的url,文中只是简单的判断是否是相对路径,但是有些url是失效的 解决办法:就是新增判断是否是真实有效url的图片 复制代码
考虑到这个问题:Passing a Shapeless Extensible Record to a Function,Travis的答案表明,每个以可扩展记录为参数的函数都必须有一个隐式选择器作为参
我通过这样的套接字发送ascii: outputStreamWriter(s + (char) 13); outputStreamWriter.flush(); 在现场,flush() 和通过网络发送
在我们正在进行的重构练习中,我们必须更改选定网站的页面模板。大多数页面都被本地化并通过下面的代码更新了他们的页面模板,但对于一些我们得到以下错误: “名称、文件名对于以下类型的项目必须是唯一的:其结构
我知道已经有Default value on generic predicate as argument了。 但是,也许现在c++ 11,c++ 14或c++ 17有了新的选择? 我如何才能使这项工作
select sum(case when NumFirstNames <> 1 then 1 else 0 end) as DifferentFirstNames, sum(case when
我已将:根证书、中间证书、服务器证书导入 Tomcat for Windows 的 Java Keystore。 这些是 VeriSign(商业)证书.. 我们不能将 keyAlias 用于连接器 -
我的问题是基于这个问题:Correct way to inherit from a virtual class with non-virtual parent . 我的理解是否正确,在问题中描述的情况
我不确定是否需要使用像 PLINQ 这样的高级技术,因为我想重新表述我之前的问题 Paralleling trading software我认为我之前的问题太复杂而且不清楚,我希望现在我准确地提取了所
这是我在这里遇到的问题(仍未解决)的延续:link 但这可能有助于理解问题所在。我只创建了一个简单的测试项目('Empty Application')并添加了一个带有 XIB 文件的 View Con
好的,所以昨天我发布了一个关于创建一个模拟电影矩阵雨的 java jframe 的问题,我希望它就像这个 php 示例一样 http://mgccl.com/2007/03/30/simple-ver
从这个线程继续: What are good algorithms for vehicle license plate detection? 我开发了我的图像处理技术来尽可能强调车牌,总体而言我很满意
这个问题在我这里的问题上继续(根据 Mystical 的建议): C code loop performance 继续我的问题,当我使用打包指令而不是标量指令时,使用内部函数的代码看起来非常相似: f
这是 My Old Question 的延续 这是我创建一个新学生对象的函数: function student(id, name, marks, mob, home){ this.id =
建立在我的 last question我想弄清楚如何.local和 .comm指令准确地工作,特别是它们如何影响 C 中的链接和持续时间。 所以我进行了以下实验: static int value;
这个问题引用这个之前的one由 Christian Metzler 在 SO 上发布. 我唯一非常有限的关于注解的经验包括使用最近 Delphi 版本中引入的 CustomAttribute。 我的问
我正在使用 Jetty 和 Continuations 来实现长轮询,但我没有找到检测客户端断开连接的方法。 我知道,在第一次运行(创建 Continuation)和任何后续运行之间的时间里,由于 H
这是 CSS Display an Image Resized and Cropped 的延续.该用户的答案似乎没问题,但我需要一些帮助来改进该答案... 问:resize(缩放)如何在运行时与图像的
我是一名优秀的程序员,十分优秀!