- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个 PEM 格式的私钥。我怎样才能从中提取公钥。我需要能够在代码中务实地执行此操作,而无需执行进程(使用 openssl)。
示例未使用的私钥:
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----
我看过很多其他 SO 文章,但它们并不是我所需要的。 c# RSA extract public key from private key Use RSA private key to generate public key? C# RSA Public Key Output Not Correct
最佳答案
为了做到这一点,我必须在这里结合几个答案:
https://stackoverflow.com/a/28407693
https://stackoverflow.com/a/32243171/645283
我结合了上述两个答案并重构了 GetRSAProviderFromPemString 所以我不需要从文件中读取私钥:
//Adapted from https://stackoverflow.com/a/32243171/645283
public class PemKeyUtils
{
const String pemprivheader = "-----BEGIN RSA PRIVATE KEY-----";
const String pemprivfooter = "-----END RSA PRIVATE KEY-----";
const String pempubheader = "-----BEGIN PUBLIC KEY-----";
const String pempubfooter = "-----END PUBLIC KEY-----";
const String pemp8header = "-----BEGIN PRIVATE KEY-----";
const String pemp8footer = "-----END PRIVATE KEY-----";
const String pemp8encheader = "-----BEGIN ENCRYPTED PRIVATE KEY-----";
const String pemp8encfooter = "-----END ENCRYPTED PRIVATE KEY-----";
static bool verbose = false;
public static RSACryptoServiceProvider GetRSAProviderFromPemFile(String pemfile)
{
string pemstring = File.ReadAllText(pemfile).Trim();
return GetRSAProviderFromPemString(pemstring);
}
public static RSACryptoServiceProvider GetRSAProviderFromPemString(String pemstr)
{
bool isPrivateKeyFile = true;
if (pemstr.StartsWith(pempubheader) && pemstr.EndsWith(pempubfooter))
isPrivateKeyFile = false;
byte[] pemkey;
if (isPrivateKeyFile)
pemkey = DecodeOpenSSLPrivateKey(pemstr);
else
pemkey = DecodeOpenSSLPublicKey(pemstr);
if (pemkey == null)
return null;
if (isPrivateKeyFile)
return DecodeRSAPrivateKey(pemkey);
else
return DecodeX509PublicKey(pemkey);
}
//-------- Get the binary RSA PUBLIC key --------
static byte[] DecodeOpenSSLPublicKey(String instr)
{
const String pempubheader = "-----BEGIN PUBLIC KEY-----";
const String pempubfooter = "-----END PUBLIC KEY-----";
String pemstr = instr.Trim();
byte[] binkey;
if (!pemstr.StartsWith(pempubheader) || !pemstr.EndsWith(pempubfooter))
return null;
StringBuilder sb = new StringBuilder(pemstr);
sb.Replace(pempubheader, ""); //remove headers/footers, if present
sb.Replace(pempubfooter, "");
String pubstr = sb.ToString().Trim(); //get string after removing leading/trailing whitespace
try
{
binkey = Convert.FromBase64String(pubstr);
}
catch (System.FormatException)
{ //if can't b64 decode, data is not valid
return null;
}
return binkey;
}
static RSACryptoServiceProvider DecodeX509PublicKey(byte[] x509Key)
{
// encoded OID sequence for PKCS #1 rsaEncryption szOID_RSA_RSA = "1.2.840.113549.1.1.1"
byte[] seqOid = { 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00 };
// --------- Set up stream to read the asn.1 encoded SubjectPublicKeyInfo blob ------
using (var mem = new MemoryStream(x509Key))
{
using (var binr = new BinaryReader(mem)) //wrap Memory Stream with BinaryReader for easy reading
{
try
{
var twobytes = binr.ReadUInt16();
switch (twobytes)
{
case 0x8130:
binr.ReadByte(); //advance 1 byte
break;
case 0x8230:
binr.ReadInt16(); //advance 2 bytes
break;
default:
return null;
}
var seq = binr.ReadBytes(15);
if (!CompareBytearrays(seq, seqOid)) //make sure Sequence for OID is correct
return null;
twobytes = binr.ReadUInt16();
if (twobytes == 0x8103) //data read as little endian order (actual data order for Bit String is 03 81)
binr.ReadByte(); //advance 1 byte
else if (twobytes == 0x8203)
binr.ReadInt16(); //advance 2 bytes
else
return null;
var bt = binr.ReadByte();
if (bt != 0x00) //expect null byte next
return null;
twobytes = binr.ReadUInt16();
if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
binr.ReadByte(); //advance 1 byte
else if (twobytes == 0x8230)
binr.ReadInt16(); //advance 2 bytes
else
return null;
twobytes = binr.ReadUInt16();
byte lowbyte = 0x00;
byte highbyte = 0x00;
if (twobytes == 0x8102) //data read as little endian order (actual data order for Integer is 02 81)
lowbyte = binr.ReadByte(); // read next bytes which is bytes in modulus
else if (twobytes == 0x8202)
{
highbyte = binr.ReadByte(); //advance 2 bytes
lowbyte = binr.ReadByte();
}
else
return null;
byte[] modint = { lowbyte, highbyte, 0x00, 0x00 }; //reverse byte order since asn.1 key uses big endian order
int modsize = BitConverter.ToInt32(modint, 0);
byte firstbyte = binr.ReadByte();
binr.BaseStream.Seek(-1, SeekOrigin.Current);
if (firstbyte == 0x00)
{ //if first byte (highest order) of modulus is zero, don't include it
binr.ReadByte(); //skip this null byte
modsize -= 1; //reduce modulus buffer size by 1
}
byte[] modulus = binr.ReadBytes(modsize); //read the modulus bytes
if (binr.ReadByte() != 0x02) //expect an Integer for the exponent data
return null;
int expbytes = binr.ReadByte(); // should only need one byte for actual exponent data (for all useful values)
byte[] exponent = binr.ReadBytes(expbytes);
// We don't really need to print anything but if we insist to...
//showBytes("\nExponent", exponent);
//showBytes("\nModulus", modulus);
// ------- create RSACryptoServiceProvider instance and initialize with public key -----
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
RSAParameters rsaKeyInfo = new RSAParameters
{
Modulus = modulus,
Exponent = exponent
};
rsa.ImportParameters(rsaKeyInfo);
return rsa;
}
catch (Exception)
{
return null;
}
}
}
}
//------- Parses binary ans.1 RSA private key; returns RSACryptoServiceProvider ---
static RSACryptoServiceProvider DecodeRSAPrivateKey(byte[] privkey)
{
byte[] MODULUS, E, D, P, Q, DP, DQ, IQ;
// --------- Set up stream to decode the asn.1 encoded RSA private key ------
MemoryStream mem = new MemoryStream(privkey);
BinaryReader binr = new BinaryReader(mem); //wrap Memory Stream with BinaryReader for easy reading
byte bt = 0;
ushort twobytes = 0;
int elems = 0;
try
{
twobytes = binr.ReadUInt16();
if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
binr.ReadByte(); //advance 1 byte
else if (twobytes == 0x8230)
binr.ReadInt16(); //advance 2 bytes
else
return null;
twobytes = binr.ReadUInt16();
if (twobytes != 0x0102) //version number
return null;
bt = binr.ReadByte();
if (bt != 0x00)
return null;
//------ all private key components are Integer sequences ----
elems = GetIntegerSize(binr);
MODULUS = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
E = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
D = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
P = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
Q = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
DP = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
DQ = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
IQ = binr.ReadBytes(elems);
Console.WriteLine("showing components ..");
if (verbose)
{
showBytes("\nModulus", MODULUS);
showBytes("\nExponent", E);
showBytes("\nD", D);
showBytes("\nP", P);
showBytes("\nQ", Q);
showBytes("\nDP", DP);
showBytes("\nDQ", DQ);
showBytes("\nIQ", IQ);
}
// ------- create RSACryptoServiceProvider instance and initialize with public key -----
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
RSAParameters RSAparams = new RSAParameters();
RSAparams.Modulus = MODULUS;
RSAparams.Exponent = E;
RSAparams.D = D;
RSAparams.P = P;
RSAparams.Q = Q;
RSAparams.DP = DP;
RSAparams.DQ = DQ;
RSAparams.InverseQ = IQ;
RSA.ImportParameters(RSAparams);
return RSA;
}
catch (Exception)
{
return null;
}
finally { binr.Close(); }
}
private static int GetIntegerSize(BinaryReader binr)
{
byte bt = 0;
byte lowbyte = 0x00;
byte highbyte = 0x00;
int count = 0;
bt = binr.ReadByte();
if (bt != 0x02) //expect integer
return 0;
bt = binr.ReadByte();
if (bt == 0x81)
count = binr.ReadByte(); // data size in next byte
else
if (bt == 0x82)
{
highbyte = binr.ReadByte(); // data size in next 2 bytes
lowbyte = binr.ReadByte();
byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
count = BitConverter.ToInt32(modint, 0);
}
else
{
count = bt; // we already have the data size
}
while (binr.ReadByte() == 0x00)
{ //remove high order zeros in data
count -= 1;
}
binr.BaseStream.Seek(-1, SeekOrigin.Current); //last ReadByte wasn't a removed zero, so back up a byte
return count;
}
//----- Get the binary RSA PRIVATE key, decrypting if necessary ----
static byte[] DecodeOpenSSLPrivateKey(String instr)
{
const String pemprivheader = "-----BEGIN RSA PRIVATE KEY-----";
const String pemprivfooter = "-----END RSA PRIVATE KEY-----";
String pemstr = instr.Trim();
byte[] binkey;
if (!pemstr.StartsWith(pemprivheader) || !pemstr.EndsWith(pemprivfooter))
return null;
StringBuilder sb = new StringBuilder(pemstr);
sb.Replace(pemprivheader, ""); //remove headers/footers, if present
sb.Replace(pemprivfooter, "");
String pvkstr = sb.ToString().Trim(); //get string after removing leading/trailing whitespace
try
{ // if there are no PEM encryption info lines, this is an UNencrypted PEM private key
binkey = Convert.FromBase64String(pvkstr);
return binkey;
}
catch (System.FormatException)
{ //if can't b64 decode, it must be an encrypted private key
//Console.WriteLine("Not an unencrypted OpenSSL PEM private key");
}
StringReader str = new StringReader(pvkstr);
//-------- read PEM encryption info. lines and extract salt -----
if (!str.ReadLine().StartsWith("Proc-Type: 4,ENCRYPTED"))
return null;
String saltline = str.ReadLine();
if (!saltline.StartsWith("DEK-Info: DES-EDE3-CBC,"))
return null;
String saltstr = saltline.Substring(saltline.IndexOf(",") + 1).Trim();
byte[] salt = new byte[saltstr.Length / 2];
for (int i = 0; i < salt.Length; i++)
salt[i] = Convert.ToByte(saltstr.Substring(i * 2, 2), 16);
if (!(str.ReadLine() == ""))
return null;
//------ remaining b64 data is encrypted RSA key ----
String encryptedstr = str.ReadToEnd();
try
{ //should have b64 encrypted RSA key now
binkey = Convert.FromBase64String(encryptedstr);
}
catch (System.FormatException)
{ // bad b64 data.
return null;
}
//------ Get the 3DES 24 byte key using PDK used by OpenSSL ----
SecureString despswd = GetSecPswd("Enter password to derive 3DES key==>");
//Console.Write("\nEnter password to derive 3DES key: ");
//String pswd = Console.ReadLine();
byte[] deskey = GetOpenSSL3deskey(salt, despswd, 1, 2); // count=1 (for OpenSSL implementation); 2 iterations to get at least 24 bytes
if (deskey == null)
return null;
//showBytes("3DES key", deskey) ;
//------ Decrypt the encrypted 3des-encrypted RSA private key ------
byte[] rsakey = DecryptKey(binkey, deskey, salt); //OpenSSL uses salt value in PEM header also as 3DES IV
if (rsakey != null)
return rsakey; //we have a decrypted RSA private key
else
{
Console.WriteLine("Failed to decrypt RSA private key; probably wrong password.");
return null;
}
}
// ----- Decrypt the 3DES encrypted RSA private key ----------
static byte[] DecryptKey(byte[] cipherData, byte[] desKey, byte[] IV)
{
MemoryStream memst = new MemoryStream();
TripleDES alg = TripleDES.Create();
alg.Key = desKey;
alg.IV = IV;
try
{
CryptoStream cs = new CryptoStream(memst, alg.CreateDecryptor(), CryptoStreamMode.Write);
cs.Write(cipherData, 0, cipherData.Length);
cs.Close();
}
catch (Exception exc)
{
Console.WriteLine(exc.Message);
return null;
}
byte[] decryptedData = memst.ToArray();
return decryptedData;
}
//----- OpenSSL PBKD uses only one hash cycle (count); miter is number of iterations required to build sufficient bytes ---
static byte[] GetOpenSSL3deskey(byte[] salt, SecureString secpswd, int count, int miter)
{
IntPtr unmanagedPswd = IntPtr.Zero;
int HASHLENGTH = 16; //MD5 bytes
byte[] keymaterial = new byte[HASHLENGTH * miter]; //to store contatenated Mi hashed results
byte[] psbytes = new byte[secpswd.Length];
unmanagedPswd = Marshal.SecureStringToGlobalAllocAnsi(secpswd);
Marshal.Copy(unmanagedPswd, psbytes, 0, psbytes.Length);
Marshal.ZeroFreeGlobalAllocAnsi(unmanagedPswd);
//UTF8Encoding utf8 = new UTF8Encoding();
//byte[] psbytes = utf8.GetBytes(pswd);
// --- contatenate salt and pswd bytes into fixed data array ---
byte[] data00 = new byte[psbytes.Length + salt.Length];
Array.Copy(psbytes, data00, psbytes.Length); //copy the pswd bytes
Array.Copy(salt, 0, data00, psbytes.Length, salt.Length); //concatenate the salt bytes
// ---- do multi-hashing and contatenate results D1, D2 ... into keymaterial bytes ----
MD5 md5 = new MD5CryptoServiceProvider();
byte[] result = null;
byte[] hashtarget = new byte[HASHLENGTH + data00.Length]; //fixed length initial hashtarget
for (int j = 0; j < miter; j++)
{
// ---- Now hash consecutively for count times ------
if (j == 0)
result = data00; //initialize
else
{
Array.Copy(result, hashtarget, result.Length);
Array.Copy(data00, 0, hashtarget, result.Length, data00.Length);
result = hashtarget;
//Console.WriteLine("Updated new initial hash target:") ;
//showBytes(result) ;
}
for (int i = 0; i < count; i++)
result = md5.ComputeHash(result);
Array.Copy(result, 0, keymaterial, j * HASHLENGTH, result.Length); //contatenate to keymaterial
}
//showBytes("Final key material", keymaterial);
byte[] deskey = new byte[24];
Array.Copy(keymaterial, deskey, deskey.Length);
Array.Clear(psbytes, 0, psbytes.Length);
Array.Clear(data00, 0, data00.Length);
Array.Clear(result, 0, result.Length);
Array.Clear(hashtarget, 0, hashtarget.Length);
Array.Clear(keymaterial, 0, keymaterial.Length);
return deskey;
}
static SecureString GetSecPswd(String prompt)
{
SecureString password = new SecureString();
Console.ForegroundColor = ConsoleColor.Gray;
Console.Write(prompt);
Console.ForegroundColor = ConsoleColor.Magenta;
while (true)
{
ConsoleKeyInfo cki = Console.ReadKey(true);
if (cki.Key == ConsoleKey.Enter)
{
Console.ForegroundColor = ConsoleColor.Gray;
Console.WriteLine();
return password;
}
else if (cki.Key == ConsoleKey.Backspace)
{
// remove the last asterisk from the screen...
if (password.Length > 0)
{
Console.SetCursorPosition(Console.CursorLeft - 1, Console.CursorTop);
Console.Write(" ");
Console.SetCursorPosition(Console.CursorLeft - 1, Console.CursorTop);
password.RemoveAt(password.Length - 1);
}
}
else if (cki.Key == ConsoleKey.Escape)
{
Console.ForegroundColor = ConsoleColor.Gray;
Console.WriteLine();
return password;
}
else if (Char.IsLetterOrDigit(cki.KeyChar) || Char.IsSymbol(cki.KeyChar))
{
if (password.Length < 20)
{
password.AppendChar(cki.KeyChar);
Console.Write("*");
}
else
{
Console.Beep();
}
}
else
{
Console.Beep();
}
}
}
static bool CompareBytearrays(byte[] a, byte[] b)
{
if (a.Length != b.Length)
return false;
int i = 0;
foreach (byte c in a)
{
if (c != b[i])
return false;
i++;
}
return true;
}
static void showBytes(String info, byte[] data)
{
Console.WriteLine("{0} [{1} bytes]", info, data.Length);
for (int i = 1; i <= data.Length; i++)
{
Console.Write("{0:X2} ", data[i - 1]);
if (i % 16 == 0)
Console.WriteLine();
}
Console.WriteLine("\n\n");
}
/// <summary>
/// Export public key from MS RSACryptoServiceProvider into OpenSSH PEM string
/// slightly modified from https://stackoverflow.com/a/28407693
/// </summary>
/// <param name="csp"></param>
/// <returns></returns>
public static string ExportPublicKey(RSACryptoServiceProvider csp)
{
StringWriter outputStream = new StringWriter();
var parameters = csp.ExportParameters(false);
using (var stream = new MemoryStream())
{
var writer = new BinaryWriter(stream);
writer.Write((byte)0x30); // SEQUENCE
using (var innerStream = new MemoryStream())
{
var innerWriter = new BinaryWriter(innerStream);
innerWriter.Write((byte)0x30); // SEQUENCE
EncodeLength(innerWriter, 13);
innerWriter.Write((byte)0x06); // OBJECT IDENTIFIER
var rsaEncryptionOid = new byte[] { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
EncodeLength(innerWriter, rsaEncryptionOid.Length);
innerWriter.Write(rsaEncryptionOid);
innerWriter.Write((byte)0x05); // NULL
EncodeLength(innerWriter, 0);
innerWriter.Write((byte)0x03); // BIT STRING
using (var bitStringStream = new MemoryStream())
{
var bitStringWriter = new BinaryWriter(bitStringStream);
bitStringWriter.Write((byte)0x00); // # of unused bits
bitStringWriter.Write((byte)0x30); // SEQUENCE
using (var paramsStream = new MemoryStream())
{
var paramsWriter = new BinaryWriter(paramsStream);
EncodeIntegerBigEndian(paramsWriter, parameters.Modulus); // Modulus
EncodeIntegerBigEndian(paramsWriter, parameters.Exponent); // Exponent
var paramsLength = (int)paramsStream.Length;
EncodeLength(bitStringWriter, paramsLength);
bitStringWriter.Write(paramsStream.GetBuffer(), 0, paramsLength);
}
var bitStringLength = (int)bitStringStream.Length;
EncodeLength(innerWriter, bitStringLength);
innerWriter.Write(bitStringStream.GetBuffer(), 0, bitStringLength);
}
var length = (int)innerStream.Length;
EncodeLength(writer, length);
writer.Write(innerStream.GetBuffer(), 0, length);
}
var base64 = Convert.ToBase64String(stream.GetBuffer(), 0, (int)stream.Length).ToCharArray();
// WriteLine terminates with \r\n, we want only \n
outputStream.Write("-----BEGIN PUBLIC KEY-----\n");
for (var i = 0; i < base64.Length; i += 64)
{
outputStream.Write(base64, i, Math.Min(64, base64.Length - i));
outputStream.Write("\n");
}
outputStream.Write("-----END PUBLIC KEY-----");
}
return outputStream.ToString();
}
// https://stackoverflow.com/a/23739932/2860309
private static void EncodeLength(BinaryWriter stream, int length)
{
if (length < 0) throw new ArgumentOutOfRangeException("length", "Length must be non-negative");
if (length < 0x80)
{
// Short form
stream.Write((byte)length);
}
else
{
// Long form
var temp = length;
var bytesRequired = 0;
while (temp > 0)
{
temp >>= 8;
bytesRequired++;
}
stream.Write((byte)(bytesRequired | 0x80));
for (var i = bytesRequired - 1; i >= 0; i--)
{
stream.Write((byte)(length >> (8 * i) & 0xff));
}
}
}
//https://stackoverflow.com/a/23739932/2860309
private static void EncodeIntegerBigEndian(BinaryWriter stream, byte[] value, bool forceUnsigned = true)
{
stream.Write((byte)0x02); // INTEGER
var prefixZeros = 0;
for (var i = 0; i < value.Length; i++)
{
if (value[i] != 0) break;
prefixZeros++;
}
if (value.Length - prefixZeros == 0)
{
EncodeLength(stream, 1);
stream.Write((byte)0);
}
else
{
if (forceUnsigned && value[prefixZeros] > 0x7f)
{
// Add a prefix zero to force unsigned if the MSB is 1
EncodeLength(stream, value.Length - prefixZeros + 1);
stream.Write((byte)0);
}
else
{
EncodeLength(stream, value.Length - prefixZeros);
}
for (var i = prefixZeros; i < value.Length; i++)
{
stream.Write(value[i]);
}
}
}
}
然后,我可以通过调用 PemKeyUtils.ExportPublicKey 来导出(更像是拼凑)公钥:
using (RSACryptoServiceProvider rsaCsp = PemKeyUtils.GetRSAProviderFromPemString(privateKeyInPemFormat))
{
return PemKeyUtils.ExportPublicKey(rsaCsp);
}
关于C# 从 RSA PEM 私钥中提取公钥,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49865042/
我需要将文本放在 中在一个 Div 中,在另一个 Div 中,在另一个 Div 中。所以这是它的样子: #document Change PIN
奇怪的事情发生了。 我有一个基本的 html 代码。 html,头部, body 。(因为我收到了一些反对票,这里是完整的代码) 这是我的CSS: html { backgroun
我正在尝试将 Assets 中的一组图像加载到 UICollectionview 中存在的 ImageView 中,但每当我运行应用程序时它都会显示错误。而且也没有显示图像。 我在ViewDidLoa
我需要根据带参数的 perl 脚本的输出更改一些环境变量。在 tcsh 中,我可以使用别名命令来评估 perl 脚本的输出。 tcsh: alias setsdk 'eval `/localhome/
我使用 Windows 身份验证创建了一个新的 Blazor(服务器端)应用程序,并使用 IIS Express 运行它。它将显示一条消息“Hello Domain\User!”来自右上方的以下 Ra
这是我的方法 void login(Event event);我想知道 Kotlin 中应该如何 最佳答案 在 Kotlin 中通配符运算符是 * 。它指示编译器它是未知的,但一旦知道,就不会有其他类
看下面的代码 for story in book if story.title.length < 140 - var story
我正在尝试用 C 语言学习字符串处理。我写了一个程序,它存储了一些音乐轨道,并帮助用户检查他/她想到的歌曲是否存在于存储的轨道中。这是通过要求用户输入一串字符来完成的。然后程序使用 strstr()
我正在学习 sscanf 并遇到如下格式字符串: sscanf("%[^:]:%[^*=]%*[*=]%n",a,b,&c); 我理解 %[^:] 部分意味着扫描直到遇到 ':' 并将其分配给 a。:
def char_check(x,y): if (str(x) in y or x.find(y) > -1) or (str(y) in x or y.find(x) > -1):
我有一种情况,我想将文本文件中的现有行包含到一个新 block 中。 line 1 line 2 line in block line 3 line 4 应该变成 line 1 line 2 line
我有一个新项目,我正在尝试设置 Django 调试工具栏。首先,我尝试了快速设置,它只涉及将 'debug_toolbar' 添加到我的已安装应用程序列表中。有了这个,当我转到我的根 URL 时,调试
在 Matlab 中,如果我有一个函数 f,例如签名是 f(a,b,c),我可以创建一个只有一个变量 b 的函数,它将使用固定的 a=a1 和 c=c1 调用 f: g = @(b) f(a1, b,
我不明白为什么 ForEach 中的元素之间有多余的垂直间距在 VStack 里面在 ScrollView 里面使用 GeometryReader 时渲染自定义水平分隔线。 Scrol
我想知道,是否有关于何时使用 session 和 cookie 的指南或最佳实践? 什么应该和什么不应该存储在其中?谢谢! 最佳答案 这些文档很好地了解了 session cookie 的安全问题以及
我在 scipy/numpy 中有一个 Nx3 矩阵,我想用它制作一个 3 维条形图,其中 X 轴和 Y 轴由矩阵的第一列和第二列的值、高度确定每个条形的 是矩阵中的第三列,条形的数量由 N 确定。
假设我用两种不同的方式初始化信号量 sem_init(&randomsem,0,1) sem_init(&randomsem,0,0) 现在, sem_wait(&randomsem) 在这两种情况下
我怀疑该值如何存储在“WORD”中,因为 PStr 包含实际输出。? 既然Pstr中存储的是小写到大写的字母,那么在printf中如何将其给出为“WORD”。有人可以吗?解释一下? #include
我有一个 3x3 数组: var my_array = [[0,1,2], [3,4,5], [6,7,8]]; 并想获得它的第一个 2
我意识到您可以使用如下方式轻松检查焦点: var hasFocus = true; $(window).blur(function(){ hasFocus = false; }); $(win
我是一名优秀的程序员,十分优秀!