在我的脚本中我有:
openssl req \ -x509 \ -new \ -nodes \ -key certs/ca/my-root-ca.key.pem \ -days 3652 \ -out certs/ca/my-root-ca.crt.pem \ -subj "/C=GB/ST=someplace/L=Provo/O=Achme/CN=${FQDN}"
在Git Bash 3.1的Windows上运行这个function给出:
Subject does not start with '/'.
尝试转义这样的主题:-subj \“/ C = UK / ST = someplace / L = Provo / O = Achme / CN = $ {FQDN} \”
依然不起作用。 有任何想法吗?
这个问题是特定于MinGW / MSYS ,它通常被用作Git for Windows包的一部分。
解决方法是传递带有前导的//
(双正斜杠)的-subj
参数,然后使用\
(反斜杠)来分隔键/值对。 喜欢这个:
"//O=Org\CN=Name"
这将会神奇地传递给预期的形式:
"/O=Org/CN=Name"
所以要回答具体的问题,你应该把脚本中的-subj
行更改为以下内容。
-subj "//C=GB\ST=someplace\L=Provo\O=Achme\CN=${FQDN}"
这应该是你需要的一切。
对于那些正在发生的事情,我可以解释这个谜。 原因是MSYS合理地认为包含斜线的参数实际上是路径。 当这些参数传递给一个没有专门针对MSYS编译的可执行文件(比如openssl
)时,它将把POSIX路径转换成Win32路径 。 这个转换的规则是相当复杂的,因为MSYS尽力覆盖大多数常见的互操作场景。 这也解释了为什么从Windows命令提示符( cmd.exe
)使用openssl
工作正常,因为没有魔术转换。
你可以像这样测试转换。
$ cmd //c echo "/CN=Name" "C:/Program Files (x86)/Git/CN=Name"
我们不能使用MSYS自带的echo
可执行文件,而是使用cmd
的echo
内置cmd
。 请注意,由于cmd
开关以/
(Windows常用命令)开头,所以我们需要用双斜线来处理。 正如我们在输出中看到的那样,参数被扩展到了一个窗口路径,这就变得清晰了,为什么openssl
确实声称Subject does not start with '/'.
。
让我们看看更多的转换。
$ cmd //c echo "//CN=Name" /CN=Name
双斜杠使得MSYS相信这个参数是一个windows风格的开关,导致剥离/
仅(无路径转换)。 你可以这样认为,我们可以使用斜杠来添加更多的键/值对。 我们来试试。
$ cmd //c echo "//O=Org/CN=Name" //O=Org/CN=Name
突然之间,双重斜线的开始并没有被剥离。 这是因为现在,斜杠跟在最初的双斜线之后,MSYS认为我们正在引用UNC路径(例如//服务器/路径)。 如果这被传递给openssl
它会跳过第一个键/值,说Subject Attribute /O has no known NID, skipped
。
以下是MinGW wiki解释此行为的相关规则:
- 一个以2或更多/开头的参数被认为是一个逃逸的Windows风格的开关,并将通过前导/删除和所有\改为/。
- 除了如果/之后有一个/后面的参数,这个参数被认为是一个UNC路径,并且前导/不会被删除。
在这个规则中,我们可以看到我们可以用来创建我们想要的参数的方法。 由于以//
开头的参数中的所有\
将被转换为plain /
。 让我们试试看。
$ cmd //c echo "//O=Org\CN=Name" /O=Org/CN=Name
而且我们可以看到它确实有效。
希望这个神秘的一点点神秘。