我需要从文件中加载以下 RSA 公钥,以便与 RSACryptoServiceProvider 类一起使用。我该怎么做?
-----BEGIN PUBLIC KEY-----
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/syEKqEkMtQL0+d
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX+izR
KbGMRtur2TYklnyVkjeeHfAggo8vWQmWesnOG55vQYHbOOFoJbk0EkwEr5R/PbKm
byXPPN8zwnS5/XXXXXXXXXXXX
-----END PUBLIC KEY-----
此代码适用于我的公钥:http://www.jensign.com/opensslkey/
这是我使用的代码
static string RSA(string input)
{
RSACryptoServiceProvider rsa = DecodeX509PublicKey(Convert.FromBase64String(GetKey()));
return (Convert.ToBase64String(rsa.Encrypt(Encoding.ASCII.GetBytes(input), false)));
}
static string GetKey()
{
return File.ReadAllText("master.pub").Replace("-----BEGIN PUBLIC KEY-----", "").Replace("-----END PUBLIC KEY-----", "");
//.Replace("\n", "");
}
private 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;
}
public 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 };
byte[] seq = new byte[15];
// --------- Set up stream to read the asn.1 encoded SubjectPublicKeyInfo blob ------
MemoryStream mem = new MemoryStream(x509key);
BinaryReader binr = new BinaryReader(mem); //wrap Memory Stream with BinaryReader for easy reading
byte bt = 0;
ushort twobytes = 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;
seq = binr.ReadBytes(15); //read the Sequence OID
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;
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 = (int)binr.ReadByte(); // should only need one byte for actual exponent data (for all useful values)
byte[] exponent = binr.ReadBytes(expbytes);
// ------- create RSACryptoServiceProvider instance and initialize with public key -----
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
RSAParameters RSAKeyInfo = new RSAParameters();
RSAKeyInfo.Modulus = modulus;
RSAKeyInfo.Exponent = exponent;
RSA.ImportParameters(RSAKeyInfo);
return RSA;
}
catch (Exception)
{
return null;
}
finally { binr.Close(); }
}
只需使用要加密的文本调用“RSA”方法即可。
最佳答案
您可以使用以下类(GetRSAProviderFromPemFile 方法)从 PEM 文件创建 RSACryptoServiceProvider。
警告: 不要未经验证就直接从 StackOverflow 复制代码!尤其不是加密代码!这段代码有错误(见评论)。您可能希望在生产中使用它之前编写并运行测试(如果您真的没有更好的选择)。我拒绝编辑代码来修复它,因为如果没有测试和活跃的维护者。
来源:
此代码似乎取自 opensslkey from this site .
版权所有 (c) 2000 JavaScience Consulting,Michel Gallant。
原始包是在类似 BSD 的许可下发布的,因此使用它可能没问题(但您可能需要仔细检查)。还有一个NuGet package同一个作者。
这是最初发布到此答案的复制粘贴源代码:
RSACryptoServiceProvider provider = PemKeyUtils.GetRSAProviderFromPemFile( @"public_key.pem" );
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 )
{
bool isPrivateKeyFile = true;
string pemstr = File.ReadAllText( pemfile ).Trim();
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" );
}
}
关于c# - 如何在 C# 中从文件加载 RSA 公钥,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11506891/
出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits
如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby中使用两个参数异步运行exe吗?我已经尝试过ruby命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何rubygems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除
鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende
我正在为一个项目制作一个简单的shell,我希望像在Bash中一样解析参数字符串。foobar"helloworld"fooz应该变成:["foo","bar","helloworld","fooz"]等等。到目前为止,我一直在使用CSV::parse_line,将列分隔符设置为""和.compact输出。问题是我现在必须选择是要支持单引号还是双引号。CSV不支持超过一个分隔符。Python有一个名为shlex的模块:>>>shlex.split("Test'helloworld'foo")['Test','helloworld','foo']>>>shlex.split('Test"
我实际上是在尝试使用RVM在我的OSX10.7.5上更新ruby,并在输入以下命令后:rvminstallruby我得到了以下回复:Searchingforbinaryrubies,thismighttakesometime.Checkingrequirementsforosx.Installingrequirementsforosx.Updatingsystem.......Errorrunning'requirements_osx_brew_update_systemruby-2.0.0-p247',pleaseread/Users/username/.rvm/log/138121
这可能是个愚蠢的问题。但是,我是一个新手......你怎么能在交互式rubyshell中有多行代码?好像你只能有一条长线。按回车键运行代码。无论如何我可以在不运行代码的情况下跳到下一行吗?再次抱歉,如果这是一个愚蠢的问题。谢谢。 最佳答案 这是一个例子:2.1.2:053>a=1=>12.1.2:054>b=2=>22.1.2:055>a+b=>32.1.2:056>ifa>b#Thecode‘if..."startsthedefinitionoftheconditionalstatement.2.1.2:057?>puts"f
我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R
我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("