从.snk文件导出密钥
先声明该文的实用性不强, 要产生一对密钥可以有更简单的方法。该文简单解释了.snk文件的格式,并给出了从中提取密钥的C#代码。
.snk文件(Strong Name Key)也可以叫签名文件,它一般用来给DotNet程序集进行强命名。它的好处是非常容易产生,也非常容易管理。我们可以在Visual Studio的项目设置中新建一个签名文件,也可以用sn.exe -k key.snk命令行来产生一个。
.snk可以只包含一个公钥,也可以同时包含公钥和私钥。其中私钥可以用来对程序集进行签名,而公钥则可以用来验证一个签名。由于该密钥实际上就是一个1024位的RSA密钥,我们也可以用.snk文件来进行RSA应用。比如进行非对称加密,进行Xml数字签名和验证等等。
目前就我知道的,snk格式没有正式公开。不过包含公钥和私钥的.snk实际上就是一个PRIVATEKEYBLOB结构。该结构的定义见:
http://msdn.microsoft.com/en-us/library/aa387401(v=vs.85).aspx
该结构由一个BLOBHEADER头结构,一个RSAPUBKEY结构,以及一些RSA钥匙数据组成。其中BLOBHEADER.bType为PRIVATEKEYBLOB(0x7),指明该文件包含了私钥;而BLOBHEADER.aiKeyAlg固定为CALG_RSA_SIGN,指明该钥匙用来签名;RSAPUBKEY.bitlen指定了RSA密钥的长度,该长度将影响那一些钥匙数据的长度,这里我们把它固定为1024位。
下列C#代码示例如何将带私钥的签名文件读入到的结构中,并导出一个RSA钥匙:
[StructLayout( LayoutKind.Sequential, Pack=1)]
struct BLOBHEADER
{
public byte bType; //PRIVATEKEYBLOB = 0x7
public byte bVersion; //Digital Signature Standard=3; CUR_BLOB_VERSION=2
public short reserved; //
public uint aiKeyAlg; //CALG_RSA_KEYX=0xa400; CALG_RSA_SIGN=0x2400
}
[StructLayout( LayoutKind.Sequential, Pack=1)]
struct RSAPUBKEY
{
public int magic; //0x32415352 ("RSA2") for public/private key; ("RSA1") for public key only
public int bitlen; //Number of bits in the modulus. A multiple of eight.
public int pubexp; //The public exponent
}
[StructLayout( LayoutKind.Sequential, Pack=1)]
struct PRIVATEKEYBLOB
{
public BLOBHEADER blobheader;
public RSAPUBKEY rsapubkey;
[MarshalAs( UnmanagedType.ByValArray, SizeConst=128)]
public byte[] modulus; //[rsapubkey.bitlen/8]; as Modulus
[MarshalAs( UnmanagedType.ByValArray, SizeConst=64)]
public byte[] prime1; //[rsapubkey.bitlen/16]; as P
[MarshalAs( UnmanagedType.ByValArray, SizeConst=64)]
public byte[] prime2; //[rsapubkey.bitlen/16]; as Q
[MarshalAs( UnmanagedType.ByValArray, SizeConst=64)]
public byte[] exponent1; //[rsapubkey.bitlen/16]; as D mod (P - 1)".
[MarshalAs( UnmanagedType.ByValArray, SizeConst=64)]
public byte[] exponent2; //[rsapubkey.bitlen/16]; as D mod (Q - 1)".
[MarshalAs( UnmanagedType.ByValArray, SizeConst=64)]
public byte[] coefficient; //[rsapubkey.bitlen/16]; as InverseQ
[MarshalAs( UnmanagedType.ByValArray, SizeConst=128)]
public byte[] privateExponent; //[rsapubkey.bitlen/8]; as D
public RSAParameters GetRSAKey()
{
RSAParameters key = new RSAParameters()
{
Modulus = this.modulus,
P = this.prime1,
Q = this.prime2,
DP = this.exponent1,
DQ = this.exponent2,
InverseQ = this.coefficient,
D = this.privateExponent,
Exponent = BitConverter.GetBytes(this.rsapubkey.pubexp),
};
Array[] arrays = {key.Modulus, key.P, key.Q, key.DP, key.DQ, key.InverseQ, key.D, key.Exponent};
foreach(Array a in arrays)
{
Array.Reverse(a);
}
return key;
}
public static RSAParameters LoadFromSNK(string filename)
{
byte[] raw = File.ReadAllBytes(filename);
if (raw.Length != Marshal.SizeOf(typeof(PRIVATEKEYBLOB)))
{
throw new InvalidOperationException("not a valid snk file with public/private key");
}
GCHandle gc = GCHandle.Alloc(raw, GCHandleType.Pinned);
PRIVATEKEYBLOB b = (PRIVATEKEYBLOB)Marshal.PtrToStructure(gc.AddrOfPinnedObject(), typeof(PRIVATEKEYBLOB));
gc.Free();
return b.GetRSAKey();
}
}
只包含公钥的.snk文件可以通过sn.exe -p key.snk public.snk来产生。这种只包含公钥的.snk文件格式则是PUBLICKEYBLOB的基础上,加上一些额外包装。PUBLICKEYBLOB结构的定义见:
http://msdn.microsoft.com/en-us/library/aa387459(v=vs.85).aspx
额外包装为4个字节的签名算法;4个字节的散列算法;以及4个字节的钥匙长度。这额外的12字节,加上PUBLICKEYBLOB的148字节,总好是(只包含公钥的).snk的总长度,160字节。
下列为代码表示:
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct PUBLICKEYBLOB
{
//.Net wrapper
public int signatureAlg; //CALG_RSA_SIGN=0x2400
public int hashAlg; //CALG_SHA1=0x8004
public int blobLength; //148
public BLOBHEADER blobheader;
public RSAPUBKEY rsapubkey;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
public byte[] modulus; //[rsapubkey.bitlen/8]; as Modulus
public RSAParameters GetRSAKey()
{
RSAParameters key = new RSAParameters()
{
Modulus = this.modulus,
Exponent = BitConverter.GetBytes(this.rsapubkey.pubexp),
};
Array[] arrays = { key.Modulus, key.Exponent };
foreach (Array a in arrays)
{
Array.Reverse(a);
}
return key;
}
}
导出公钥还有其他的办法。一个办法是将.snk导入到当前系统的钥匙容器中,既sn.exe -i key.snk mykeycontainer。然后再用RSACrytoServiceProvider.ExportParameters来导出公钥:
CspParameters cp = new CspParameters(1);
cp.KeyContainerName = "mykeycontainer";
cp.KeyNumber = (int)KeyNumber.Signature;
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cp);
RSAParameters publicKey = rsa.ExportParameters(false);
不过这种方法对私钥无效。虽然sn.exe可以将钥匙导入到容器的KeyNumber.Signature上,但该钥匙被标志为不可导出。也就是说调用rsa.ExportParameters(true)将抛出异常。
从.snk文件导出密钥的更多相关文章
- C#+OpenGL+FreeType显示3D文字(1) - 从TTF文件导出字形贴图
C#+OpenGL+FreeType显示3D文字(1) - 从TTF文件导出字形贴图 +BIT祝威+悄悄在此留下版了个权的信息说: 最近需要用OpenGL绘制文字,这是个很费时费力的事.一般的思路就是 ...
- loadrunner实现excel文件导出操作
项目中需要对“商品信息”进行查询及导出,但是loadrunner并不能录制到“保存”这一操作. 项目介绍:flex+Http协议: 不能录制的原因: 在我们点击了“导出”按钮后,服务端已经生成一份我们 ...
- C#进行Visio二次开发之文件导出及另存Web页面
在我前面很多关于Visio的开发过程中,介绍了各种Visio的C#开发应用场景,包括对Visio的文档.模具文档.形状.属性数据.各种事件等相关的基础处理,以及Visio本身的整体项目应用,虽然时间过 ...
- 如何利用.snk文件生成DLL文件中的Publickeytoken
1.在该路径下C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin查找是否有sn.exe. 没有的话,从网上下载,注意需要的版本. 2.打开c ...
- Ado.Net小练习01(数据库文件导出,导入)
数据库文件导出主要程序: <span style="font-family: Arial, Helvetica, sans-serif;"><span style ...
- .Net 程序集 签名工具sn.exe 密钥对SNK文件 最基本的用法
阐述签名工具这个概念之前,我先说说它不是什么: 1.它不是用于给程序集加密的工具,它与阻止Reflector或ILSpy对程序集进行反编译一毛钱关系都没有. 2.它很讨厌人们把它和加密联系在一起. 我 ...
- JAVA实用案例之文件导出(JasperReport踩坑实录)
写在最前面 想想来新公司也快五个月了,恍惚一瞬间. 翻了翻博客,因为太忙,也有将近五个多月没认真总结过了. 正好趁着今天老婆出门团建的机会,记录下最近这段时间遇到的大坑-JasperReport. 六 ...
- 文件导出也可以这么写【js+blob】
文件导出在软件开发中是个比较常用的功能,基本原理也很简单: 浏览器向后台发送一个Get请求 后台处理程序接收到请求后,经过处理,返回二进制文件流 浏览器接收到二进制文件流后提示下载文件 调用的js方法 ...
- 转载:.Net 程序集 签名工具sn.exe 密钥对SNK文件 最基本的用法
.Net 程序集 签名工具sn.exe 密钥对SNK文件 最基本的用法 阐述签名工具这个概念之前,我先说说它不是什么: 1.它不是用于给程序集加密的工具,它与阻止Reflector或ILSpy对程序集 ...
随机推荐
- 【API】网络编程模型、多线程
1.网络通信编程 1)网络通信模型基础知识 TCP Server: WSAStartup() socket() bind() linsten() accept() send/recv() closes ...
- python3 str.format()的使用
基本格式 {字段名!转换字段:格式说明符} 字段名:省略:数字:变量名 'name is {}, age is {}'.format('peter',25) 'name is {1}, age is ...
- Singleton单例对象的使用
namespace www{ public abstract class SingletonManager<T> : ISingletonManager where T : class, ...
- 使用 Application Loader提交IPA文件到苹果市场
打包.导出ipa包后剩下的就是要将ipa包推到appstore.Application Loader是苹果提供的ipa包提交工具. 1.启动Application Loader 打开xcode,在xc ...
- ssh隐藏的sftp功能的使用
sftp是Secure File Transfer Protocol的缩写,安全文件传送协议.可以为传输文件提供一种安全的加密方法.sftp 与 ftp 有着几乎一样的语法和功能.SFTP 为 SSH ...
- JS实现集合和ECMA6集合
集合类似于数组,但是集合中的元素是唯一的,没有重复值的.就像你学高中数学的概念一样,集合还可以做很多比如,并集,交集,差集的计算.在ECMA6之前,JavaScript没有提供原生的Set类,所以只能 ...
- MVC4是不是类似于html页+ashx页之间用JSON通过AJAX交换数据这种方式、?
不是,可以讲mvc模式是借鉴于java下面的mvc开发模式,为开发者公开了更多的内容和控制,更易于分工合作,与单元测试,借用官方的说法:MVC (Model.View.Controller)将一个We ...
- hdu 2519 求组合数
求组合数 如果求C5 3 就是5*4*3/3*2*1 也就是(5/3)*(4/2)*(3/1) Sample Input5 //T3 2 //C3 25 34 43 68 0 Sample Outpu ...
- 最小生成树问题(prim算法)POJ-1258 Agri-Net
/* 这个题很水,但是,莫名其妙runtime error一晚上,重写了一遍就又没了,很伤心! 题意很简单,大致为n个村庄,连光缆,要求连上所有村庄的长度最短. 输入n,接着是n*n的矩阵,直接用pr ...
- java线程中断的办法
目录 中断线程相关的方法 中断线程 for循环标记退出 阻塞的退出线程 使用stop()方法停止线程 中断线程相关的方法 中断线程有一些相应的方法,这里列出来一下. 注意,如果是Thread.meth ...