ESP32 SSL 连接在 CA 证书为常量时有效,但在从文件中读取时无效
ESP32 SSL connection works when CA Certificate is a constant, but not when read from a file
我有以下用于 ESP32 的 Arduino 代码:
if(!SPIFFS.begin(true)) {
Serial.println("Error mounting SPIFFS.");
}
File file = SPIFFS.open("/root.cer");
if(!file) {
Serial.println("Error opening the file.");
}
Serial.println("CA Root certificate: ");
String ca_cert = file.readString();
Serial.println(ca_cert);
espClient.setCACert(ca_cert.c_str());
file.close();
这是加载文件和设置WiFiClientSecure的CA证书的相关代码。此代码无效。
但是,如果我将 espClient.setCACert(ca_cert.c_str());
替换为 espClient.setCACert(ROOTCERT);
,其中 ROOTCERT
定义如下:
#define ROOTCERT "-----BEGIN CERTIFICATE-----\n" \
"MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/\n" \
"MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\n" \
"DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow\n" \
"PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD\n" \
"Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\n" \
"AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O\n" \
"rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq\n" \
"OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b\n" \
"xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw\n" \
"7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD\n" \
"aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV\n" \
"HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG\n" \
"SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69\n" \
"ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr\n" \
"AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz\n" \
"R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5\n" \
"JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo\n" \
"Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ\n" \
"-----END CERTIFICATE-----\n"
代码有效。
ROOTCERT 字符串直接取自证书文件,因此它们必须相同。
证书文件是使用Windows的证书导出器下载和导出的。我试过转换行结尾无济于事。
编辑:我找到了线索。
如果我执行以下操作:
String constString = ROOTCERT;
espClient.setCACert(constString.c_str());
同样不行。
我添加了这段代码:
if(strcmp(constString.c_str(), ROOTCERT))
Serial.println("Constant and converted string are equal.");
else
Serial.println("Constant and converted string are different.");
并打印 "Constant and converted string are different."
所以 .c_str()
的工作方式似乎存在某种问题?不过,我不知道这可能是什么。当打印到控制台时,.c_str()
、ROOTCERT 和 ca_cert String
都显示为相同。
我在这里完全糊涂了。
原来我用错了strcmp()
。还是不行。
折腾了一圈,终于搞定了
所以 .c_str()
只是指向 String
对象内部缓冲区的另一种方式。
不知怎的,这把事情搞砸了。使用此代码修复它。
char *dest;
dest = (char *)malloc(sizeof(char) * (ca_cert.length()+1));
strcpy(dest, ca_cert.c_str());
espClient.setCACert(dest);
我有以下用于 ESP32 的 Arduino 代码:
if(!SPIFFS.begin(true)) {
Serial.println("Error mounting SPIFFS.");
}
File file = SPIFFS.open("/root.cer");
if(!file) {
Serial.println("Error opening the file.");
}
Serial.println("CA Root certificate: ");
String ca_cert = file.readString();
Serial.println(ca_cert);
espClient.setCACert(ca_cert.c_str());
file.close();
这是加载文件和设置WiFiClientSecure的CA证书的相关代码。此代码无效。
但是,如果我将 espClient.setCACert(ca_cert.c_str());
替换为 espClient.setCACert(ROOTCERT);
,其中 ROOTCERT
定义如下:
#define ROOTCERT "-----BEGIN CERTIFICATE-----\n" \
"MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/\n" \
"MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\n" \
"DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow\n" \
"PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD\n" \
"Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\n" \
"AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O\n" \
"rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq\n" \
"OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b\n" \
"xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw\n" \
"7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD\n" \
"aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV\n" \
"HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG\n" \
"SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69\n" \
"ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr\n" \
"AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz\n" \
"R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5\n" \
"JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo\n" \
"Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ\n" \
"-----END CERTIFICATE-----\n"
代码有效。
ROOTCERT 字符串直接取自证书文件,因此它们必须相同。
证书文件是使用Windows的证书导出器下载和导出的。我试过转换行结尾无济于事。
编辑:我找到了线索。
如果我执行以下操作:
String constString = ROOTCERT;
espClient.setCACert(constString.c_str());
同样不行。
我添加了这段代码:
if(strcmp(constString.c_str(), ROOTCERT))
Serial.println("Constant and converted string are equal.");
else
Serial.println("Constant and converted string are different.");
并打印 "Constant and converted string are different."
所以 .c_str()
的工作方式似乎存在某种问题?不过,我不知道这可能是什么。当打印到控制台时,.c_str()
、ROOTCERT 和 ca_cert String
都显示为相同。
我在这里完全糊涂了。
原来我用错了strcmp()
。还是不行。
折腾了一圈,终于搞定了
所以 .c_str()
只是指向 String
对象内部缓冲区的另一种方式。
不知怎的,这把事情搞砸了。使用此代码修复它。
char *dest;
dest = (char *)malloc(sizeof(char) * (ca_cert.length()+1));
strcpy(dest, ca_cert.c_str());
espClient.setCACert(dest);