首页 新闻 会员 周边 捐助

如何将PuttyGen.exe 基于SSH-2 RSA生成的Public key 转成 pem(OpenSSH)或 RSA XML KEY 格式

0
悬赏园豆:120 [已解决问题] 解决于 2015-12-16 12:23

如题, 我的最初的需求是这个样子的:系统支持WebService和SFTP两种方式的数据交换,现在已有了SFTP,要新增WS。 我们要求客户提交数据时,交对数据进行数据签名(基于RSA)。 所以想两咱试共用一对key, 但PuttyGen,生成的并不是一个标准的key格式。

现在我能所到的是, C#能处理PEM和XML格式的Key. 对于private key,PuttyGen就有一个工具将它转成pem(OpenSSL)格式的,这个OK;但对于public key,一直没找到如何转成能用的格式。

 

求大神!!!

问题补充:

我现在已可以生成pem格式的key,但还有问题

第一种方式,通过private key(pem) 生成 pem格式的public 这个已经测试通过

openssl rsa -in ~/.ssh/private.pem -pubout > ~/.ssh/publickkey.x509

第二种方式,用ssh-keygen把把PuttyGen 生成的public key转面ssh-keygen 格式的,然后再通过另一个命令,将它转成pem格式的。命令如下:

// convert public_putty.pub to public_openssl.pub
ssh-keygen -i -f ~/.ssh/public_putty.pub > ~/.ssh/public_openssl.pub
// convert openssl public key to pem format 
ssh-keygen -f ~/.ssh/public_openssl.pub -e -m pem >~/.ssh/public_pem.pem

这两种方式都能生成pem 格式的 public key.但结果不一样。。。第二种方式生成的key用不了。我是想用第二种方式的,因为这对key是由客户生成,他们只能给我们public key,总不能去要求客户帮我们转格式吧。 请大家帮我看下,第二种方式中,是不是哪里错了?我感觉最后那个命令可能错了

下面是一些各个相关的key

Putty生成的 private key

AAAAgCCkRto2vuhbDglO8RWsuxpBjoIi0BvytXvyRYwWKC1zFKrbeC80qO5yzRnz
/GgepgU2JvoKcAGAwkNwTnjv/90xAIJfwJjNZiWYWqKjUYOddzN2gX+0w95S7wAs
cRS/GcyVdmxHN/1snX9SS5IqpHIyeeF3psG3jYOPm70AxFaZAAAAQQDkgpYaSHrM
2ZGJUAMs4C5WWF3+ZP/vuZV2TpAd7/hKVJTQfZjEBY2c1bgaWLoF98FPvVbJo/fA
1e2lnjf1kjczAAAAQQDBSm9BeqEcsgXE8MsIXqiAFLFSTFvmQ8Rp0WaWEzF1CcqS
8iWZyNIYeNe+EJIWKxEtJgpvOdyRgm5ssJ9TT29TAAAAQQDkYVaYqYc/2OYEopIJ
G5tAiGZoUjjQ3lKt0560kIPyQvWPJZDjnMnPIKj16Sgom728JER3uQ60pB1llCx4
vMLz

Putty生成的publc key(整个文本)

---- BEGIN SSH2 PUBLIC KEY ----
Comment: "rsa-key-20151216"
AAAAB3NzaC1yc2EAAAABJQAAAIEArIjkOEXxFU8BDKFDcpEBisg6ZrgC3N5RjyUm
dr5CFM3/hxpWsF987F7OZJvtAcaSG4vyl1u9vs0nZHYxEYbat1+rJDFPaCc5y7yy
Kd2kjoR1aHnwI2zkFZZ8957rKbF5Bnlz+rGtLYWznotmdUasm9DVUh8GHWWyE3cY
UJYUAok=
---- END SSH2 PUBLIC KEY ----

Putty 转换生成的pem 格式的private key

MIICWwIBAAKBgQCsiOQ4RfEVTwEMoUNykQGKyDpmuALc3lGPJSZ2vkIUzf+HGlaw
X3zsXs5km+0BxpIbi/KXW72+zSdkdjERhtq3X6skMU9oJznLvLIp3aSOhHVoefAj
bOQVlnz3nuspsXkGeXP6sa0thbOei2Z1Rqyb0NVSHwYdZbITdxhQlhQCiQIBJQKB
gCCkRto2vuhbDglO8RWsuxpBjoIi0BvytXvyRYwWKC1zFKrbeC80qO5yzRnz/Gge
pgU2JvoKcAGAwkNwTnjv/90xAIJfwJjNZiWYWqKjUYOddzN2gX+0w95S7wAscRS/
GcyVdmxHN/1snX9SS5IqpHIyeeF3psG3jYOPm70AxFaZAkEA5IKWGkh6zNmRiVAD
LOAuVlhd/mT/77mVdk6QHe/4SlSU0H2YxAWNnNW4Gli6BffBT71WyaP3wNXtpZ43
9ZI3MwJBAMFKb0F6oRyyBcTwywheqIAUsVJMW+ZDxGnRZpYTMXUJypLyJZnI0hh4
174QkhYrES0mCm853JGCbmywn1NPb1MCQQCBseZ9nsI86jAB03dsfzzk5gvVk0Un
MfriSEP1UNkHl8oVd7eR2aNm2io4d4ws5pBP2ipWxNi5jizvS/Y/RSY/AkA+sFtv
LrDLCU36rvW9hnvWg0Btt+Z0Mad8Q+nre9iwVjPcoY+nf2a71CpLev7ybtUjZkiS
xqhmiyq7d42eeqClAkEA5GFWmKmHP9jmBKKSCRubQIhmaFI40N5SrdOetJCD8kL1
jyWQ45zJzyCo9ekoKJu9vCREd7kOtKQdZZQseLzC8w==

第一种方式中,根据 private key(pem)生成的 public key(pem):正确

MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCsiOQ4RfEVTwEMoUNykQGKyDpm
uALc3lGPJSZ2vkIUzf+HGlawX3zsXs5km+0BxpIbi/KXW72+zSdkdjERhtq3X6sk
MU9oJznLvLIp3aSOhHVoefAjbOQVlnz3nuspsXkGeXP6sa0thbOei2Z1Rqyb0NVS
HwYdZbITdxhQlhQCiQIBJQ==

第二种方式,第一步,根据public key(putty)生成的public key(openssl)(整个文本)

ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEArIjkOEXxFU8BDKFDcpEBisg6ZrgC3N5RjyUmdr5CFM3/hxpWsF987F7OZJvtAcaSG4vyl1u9vs0nZHYxEYbat1+rJDFPaCc5y7yyKd2kjoR1aHnwI2zkFZZ8957rKbF5Bnlz+rGtLYWznotmdUasm9DVUh8GHWWyE3cYUJYUAok=

第二种方式,第二步,根据public key(openssl) 生成的public key(pem)

MIGHAoGBAKyI5DhF8RVPAQyhQ3KRAYrIOma4AtzeUY8lJna+QhTN/4caVrBffOxe
zmSb7QHGkhuL8pdbvb7NJ2R2MRGG2rdfqyQxT2gnOcu8sindpI6EdWh58CNs5BWW
fPee6ymxeQZ5c/qxrS2Fs56LZnVGrJvQ1VIfBh1lshN3GFCWFAKJAgEl

 

Mike.Jiang的主页 Mike.Jiang | 初学一级 | 园豆:127
提问于:2015-12-15 17:05
< >
分享
最佳答案
0

补充二:问题已解决

原来是自己C#那套load public key的方法,并不适合这种pem格式的。 将第二方式中的,第二个命令中的 -pem 改成 -pkcs8就OK了。随便发下那套load rsa key类(从网上找来的)。

public class RSACommonHelper
    {
        public static string SignData(string privateKey, string input)
        {
            RSACryptoServiceProvider key = CreateRsaProviderFromPrivateKey(privateKey);

            RSAPKCS1SignatureFormatter formatter = new RSAPKCS1SignatureFormatter(key);
            formatter.SetHashAlgorithm("MD5");
            byte[] inputArr = Convert.FromBase64String(input);
            byte[] singnatureArr = formatter.CreateSignature(inputArr);

            return Convert.ToBase64String(singnatureArr);
        }

        public static bool VerifyData(string publicKey, string expectStr, string signatureStr)
        {
            try
            {
                RSACryptoServiceProvider key = CreateRsaProviderFromPublicKey(publicKey);

                RSAPKCS1SignatureDeformatter deformatter = new RSAPKCS1SignatureDeformatter(key);
                deformatter.SetHashAlgorithm("MD5");
                byte[] expectArr = Convert.FromBase64String(expectStr);
                byte[] rgbSignature = Convert.FromBase64String(signatureStr);

                if (deformatter.VerifySignature(expectArr, rgbSignature))
                {
                    return true;
                }
                return false;
            }
            catch
            {
                return false;
            }
        }

        public static string GetHash(string m_strSource)
        {
            HashAlgorithm algorithm = HashAlgorithm.Create("MD5");

            byte[] bytes = Encoding.GetEncoding("UTF-8").GetBytes(m_strSource);

            byte[] inArray = algorithm.ComputeHash(bytes);

            return Convert.ToBase64String(inArray);
        }

        private static RSACryptoServiceProvider CreateRsaProviderFromPrivateKey(string privateKey)
        {
            var privateKeyBits = System.Convert.FromBase64String(privateKey);

            var RSA = new RSACryptoServiceProvider();
            var RSAparams = new RSAParameters();

            using (BinaryReader binr = new BinaryReader(new MemoryStream(privateKeyBits)))
            {
                byte bt = 0;
                ushort twobytes = 0;
                twobytes = binr.ReadUInt16();
                if (twobytes == 0x8130)
                    binr.ReadByte();
                else if (twobytes == 0x8230)
                    binr.ReadInt16();
                else
                    throw new Exception("Unexpected value read binr.ReadUInt16()");

                twobytes = binr.ReadUInt16();
                if (twobytes != 0x0102)
                    throw new Exception("Unexpected version");

                bt = binr.ReadByte();
                if (bt != 0x00)
                    throw new Exception("Unexpected value read binr.ReadByte()");

                RSAparams.Modulus = binr.ReadBytes(GetIntegerSize(binr));
                RSAparams.Exponent = binr.ReadBytes(GetIntegerSize(binr));
                RSAparams.D = binr.ReadBytes(GetIntegerSize(binr));
                RSAparams.P = binr.ReadBytes(GetIntegerSize(binr));
                RSAparams.Q = binr.ReadBytes(GetIntegerSize(binr));
                RSAparams.DP = binr.ReadBytes(GetIntegerSize(binr));
                RSAparams.DQ = binr.ReadBytes(GetIntegerSize(binr));
                RSAparams.InverseQ = binr.ReadBytes(GetIntegerSize(binr));
            }

            RSA.ImportParameters(RSAparams);
            return RSA;
        }

        private static int GetIntegerSize(BinaryReader binr)
        {
            byte bt = 0;
            byte lowbyte = 0x00;
            byte highbyte = 0x00;
            int count = 0;
            bt = binr.ReadByte();
            if (bt != 0x02)
                return 0;
            bt = binr.ReadByte();

            if (bt == 0x81)
                count = binr.ReadByte();
            else
                if (bt == 0x82)
                {
                    highbyte = binr.ReadByte();
                    lowbyte = binr.ReadByte();
                    byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
                    count = BitConverter.ToInt32(modint, 0);
                }
                else
                {
                    count = bt;
                }

            while (binr.ReadByte() == 0x00)
            {
                count -= 1;
            }
            binr.BaseStream.Seek(-1, SeekOrigin.Current);
            return count;
        }

        private static RSACryptoServiceProvider CreateRsaProviderFromPublicKey(string publicKeyString)
        {
            // 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[] x509key;
            byte[] seq = new byte[15];
            int x509size;

            x509key = Convert.FromBase64String(publicKeyString);
            x509size = x509key.Length;

            // ---------  Set up stream to read the asn.1 encoded SubjectPublicKeyInfo blob  ------
            using (MemoryStream mem = new MemoryStream(x509key))
            {
                using (BinaryReader binr = new BinaryReader(mem))  //wrap Memory Stream with BinaryReader for easy reading
                {
                    byte bt = 0;
                    ushort twobytes = 0;

                    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);

                    int firstbyte = binr.PeekChar();
                    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;
                }

            }
        }

        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;
        }
    }
View Code
Mike.Jiang | 初学一级 |园豆:127 | 2015-12-16 12:22
其他回答(1)
0

请看支付宝SDK

花儿笑弯了腰 | 园豆:264 (菜鸟二级) | 2015-12-19 18:31
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册