我正在尝试编写一些C代码,使我能够向厨师服务器发出请求。跟随
documentation for the chef server API
,我正在尝试在我的c代码中签名规范头,以便可以向服务器进行身份验证并发出请求。
我找到了下面的剧本
in the chef docs
(请参见“curl”)下的内容,它适用于我的客户证书。调用此脚本将从服务器返回预期的响应json。脚本中用于对规范头签名的部分是:
method="GET"
hashed_path=$(echo -n "/organizations/[org]/nodes" | openssl dgst -sha1 -binary | openssl enc -base64) #where [org] is my organization
hashed_body=$(echo -n "" | openssl dgst -sha1 -binary | openssl enc -base64)
timestamp=$(date -u "+%Y-%m-%dT%H:%M:%SZ")
canonical_request="Method:$method\nHashed Path:$hashed_path\nX-Ops-Content-Hash:$hashed_body\nX-Ops-Timestamp:$timestamp\nX-Ops-UserId:$client_name"
auth_headers=$(printf "$canonical_request" | openssl rsautl -sign -inkey \
"$(_chef_dir)/${client_name}.pem" | openssl enc -base64 | _chomp | awk '{ll=int(length/60);i=0; \
while (i<=ll) {printf " -H X-Ops-Authorization-%s:%s", i+1, substr($0,i*60+1,60);i=i+1}}')
以上代码片段的重要部分是
$(printf "$canonical_request" | openssl rsautl -sign -inkey "$(_chef_dir)/${client_name}.pem" | openssl enc -base64
.
我有一些C代码
dotnet-chef-api on GitHub
我想让他们做同样的事。它使用
BouncyCastle crypto libraries
签署内容。
private string Sign(string privateKey)
{
var method = _method.ToString().ToUpperInvariant(); //evals to 'GET'
var hashedPath = _requestUri.AbsolutePath.ToBase64EncodedSha1String(); //evals to hash of '/organizations/[org]/nodes'
var contentHash = _body.ToBase64EncodedSha1String(); //evals to hash of empty string
var canonicalHeader = $"Method:{method}\nHashed Path:{hashedPath}\nX-Ops-Content-Hash:{contentHash}\nX-Ops-Timestamp:{_timestamp}\nX-Ops-UserId:{_client}";
var input = Encoding.UTF8.GetBytes(canonicalHeader);
using (var stringReader = new StringReader(privateKey))
{
var pemReader = new PemReader(stringReader);
var key = ((AsymmetricCipherKeyPair) pemReader.ReadObject()).Private;
var signer = new RsaDigestSigner(new NullDigest());
signer.Init(true, key);
signer.BlockUpdate(input, 0, input.Length);
return Convert.ToBase64String(signer.GenerateSignature());
}
}
我已经通过调试器和许多
echo
声明bash脚本中的规范头与c代码中的规范头完全相同。不过,我完全被签下了。我从github项目中提取的代码没有改变,但是生成的base64字符串与从bash脚本中获取的字符串不同(去掉了时间戳)。
我如何在c中以与使用openssl工具签名相同的方式对某些内容进行签名?我尝试过将“nulldigest”切换为其他类型,但没有找到与openssl二进制文件产生相同base64结果的类型。如果已经存在于.NET框架中,我也愿意提供更好的方法来实现这一点。