欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C#生成putty格式的ppk文件

 更新時間:2022年07月04日 09:05:58   作者:波斯馬  
這篇文章介紹了C#生成putty格式ppk文件的方法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下

背景

2022國家級護(hù)網(wǎng)行動即將開啟,根據(jù)阿里云給出的安全建議,需要將登陸Linux的方式改為密鑰對方式。我這里使用的遠(yuǎn)程工具是自己開發(fā)的,能夠同時管理Windows和Linux,但是以前不支持密鑰對的登陸方式,所以需要改造一下。

護(hù)網(wǎng)行動是什么?護(hù)網(wǎng)行動從2016年開始,是一場由公安部組織的網(wǎng)絡(luò)安全攻防演練,目的是針對全國范圍的真實網(wǎng)絡(luò)目標(biāo)為對象的實戰(zhàn)攻防活動,旨在發(fā)現(xiàn)、暴露和解決安全問題,檢驗我國各大企事業(yè)單位、部屬機(jī)關(guān)的網(wǎng)絡(luò)安全防護(hù)水平和應(yīng)急處置能力。護(hù)網(wǎng)行動每年舉辦一次,為期2-3周。

我使用的遠(yuǎn)程工具 RDManager,這個工具訪問Linux使用了putty,putty的密鑰對登陸方式使用的是自有格式的ppk文件,但是阿里云上下載的是pem格式的密鑰文件,所以需要將pem格式轉(zhuǎn)換為ppk格式。

思路

putty本身提供了一個工具,可以將其他格式的密鑰文件轉(zhuǎn)換為自有的ppk文件,這個工具的名字是puttygen。在linux上可以通過命令進(jìn)行轉(zhuǎn)換,在Windows上則必須使用GUI工具手動操作,這多有不便。我期望的是能通過編程的方式進(jìn)行這個轉(zhuǎn)換,這樣只需要在RDManger中上傳pem文件,就可以自動轉(zhuǎn)換為putty的ppk格式的文件,不需要再去使用puttygen。

首先查了下有沒有現(xiàn)成的輪子,經(jīng)過多次尋找,在Github上找到了一個項目:pem2ppk (https://github.com/akira345/pem2ppk),這個項目看名字就知道很貼合我的需求,它的主要功能就是讀取pem文件,然后輸出為ppk文件。我最終的解決方案主體也是從此而來。不過這個程序有兩個問題:

  • 1、不是所有的pem文件都能轉(zhuǎn)換成功,網(wǎng)上也是有人說成功了,有人說不行。
  • 2、不支持對密鑰進(jìn)行加密,別人拿走了這個ppk文件就可以直接使用。puttygen是有這個功能的。

除此之外,很難再找到比較貼合需求的資料了。怎么辦?其實這個Github項目的很大一部分代碼來源于另一篇文章:https://antonymale.co.uk/generating-putty-key-files.html,作者提到可以去看putty的源碼。

受此啟發(fā),我也可以去看putty的源碼,然后將相關(guān)處理翻譯為C#的實現(xiàn),這樣應(yīng)該是可以解決問題的。

實現(xiàn)

putty的源碼官網(wǎng)上就可以下載到,不過我看的是一個幾年前的版本:https://github.com/KasperDeng/putty,這個版本和新版本的主要邏輯都是一樣的,搞懂C語言的若干函數(shù)和數(shù)據(jù)類型就很容易理解,而且舊版本更原始,沒有那么多的抽象,反而更容易理解。

輸出ppk內(nèi)容不正確的問題

這個問題主要是由于填充(padding)使用不當(dāng)造成的,pem2ppk項目在輸出密鑰的各個屬性時都使用了前置填充,而putty并不是固定的都加了填充。

看putty的代碼實現(xiàn):https://github.com/KasperDeng/putty/blob/037a4ccb6e731fafc4cc77c0d16f80552fd69dce/putty-src/sshrsa.c#L654

    dlen = (bignum_bitcount(rsa->private_exponent) + 8) / 8;
    plen = (bignum_bitcount(rsa->p) + 8) / 8;
    qlen = (bignum_bitcount(rsa->q) + 8) / 8;
    ulen = (bignum_bitcount(rsa->iqmp) + 8) / 8;
    bloblen = 16 + dlen + plen + qlen + ulen;

這段代碼是計算密鑰的各個屬性的值的字節(jié)數(shù),然后用于初始化一個大的字節(jié)數(shù)組,將這些數(shù)據(jù)寫進(jìn)去。bignum_bitcount是計算值的比特位數(shù),除以8就是得到字節(jié)數(shù),為什么還要加8呢?這是因為C語言中除法的結(jié)果是向下取整的,比如數(shù)學(xué)計算結(jié)果是1.5,那么C語言中得到的就是1,為了不讓任何一個比特丟失,所以這里加了一個8,預(yù)留好充足的空間。

再來看pem2ppk中的實現(xiàn):https://github.com/akira345/pem2ppk/blob/d2baee08064953280984607d1e4ae1183127e5ad/PEM2PPK/PuttyKeyFileGenerator.cs#L24

private const int prefixSize = 4;
private const int paddedPrefixSize = prefixSize + 1;
byte[] publicBuffer = new byte[3 + keyType.Length + paddedPrefixSize + keyParameters.Exponent.Length +
                                           paddedPrefixSize + keyParameters.Modulus.Length + 1];

這里keyParameters.Exponent和keyParameters.Modulus是公鑰的兩個屬性,可以看到前邊加了一個固定的長度paddedPrefixSize,這個paddedPrefixSize=prefixSize + 1,這里邊的1就對應(yīng)putty中的+8邏輯。

不過固定+1是有問題的,可以想一下C#和C語言在處理這些屬性值時的差別。

在putty中如果數(shù)據(jù)比特數(shù)不能被8整除,那么+8之后再整除就可以得到正確的字節(jié)數(shù),否則就會少1個字節(jié);如果數(shù)據(jù)能被8整除,那么+8就會多1個空的字節(jié),這個多的字節(jié)就是padding了。所以能被8整除的時候才會有這個padding。

在C#中開始處理的時候就已經(jīng)都是字節(jié)了,所以C#中不需要處理位數(shù)不能被8整除的問題,但是需要在能被8整除的時候增加一個空字節(jié),C#中如何判斷數(shù)據(jù)的位數(shù)能被8整除呢?可以認(rèn)為數(shù)據(jù)首byte的最高位是1的時候,比特數(shù)就能被8整數(shù),此時最小二進(jìn)制數(shù)是10000000,比它小的數(shù)就可以被舍棄掉至少1位。10000000也就是128,因此凡是大于等于這個數(shù)的都是能被8整數(shù)的,也就是需要padding的。

所以可以這樣判斷是否需要增加padding:https://gist.github.com/bosima/ee6630d30b533c7d7b2743a849e9b9d0#file-puttykeyfilegenerator-cs-L190

	private static bool CheckIsNeddPadding(byte[] bytes)
	{
		return bytes[0] >= 128;
	}

	private static int GetPrefixSize(byte[] bytes)
	{
		return CheckIsNeddPadding(bytes) ? paddedPrefixSize : prefixSize;
	}

實現(xiàn)ppk加密

pem2ppk項目中沒有對key進(jìn)行加密的實現(xiàn),網(wǎng)上也沒有找到C#的源代碼可以實現(xiàn)這個功能。但是這個功能很關(guān)鍵,在RDManager中所有的密碼都是加密處理的,這樣服務(wù)器賬號落盤的時候安全性才能有比較好的保障,但是阿里云導(dǎo)出的pem是沒有加密的,雖然puttygen也可以給pem加密,但是還不是不能將加密以編程的方式集成到RDManager中。

解決這個問題的方式還是搬運putty的實現(xiàn)方式,將C語言的實現(xiàn)轉(zhuǎn)換為C#的實現(xiàn)。其中有兩個關(guān)鍵的處理:一是要在計算Private-MAC的值時給私鑰增加padding,二是使用AES256進(jìn)行加密處理。至于putty為什么要這樣處理,我沒有研究,只是照搬過來。

主要看下AES256加密的處理,有些參數(shù)很關(guān)鍵:

byte[] passKey = new byte[40];
...
byte[] iv = new byte[16];
byte[] aesKey = new byte[32];
Buffer.BlockCopy(passKey, 0, aesKey, 0, 32);
using (RijndaelManaged rijalg = new RijndaelManaged())
{
	rijalg.BlockSize = 128;
	rijalg.KeySize = 256;
	rijalg.Padding = PaddingMode.None;
	rijalg.Mode = CipherMode.CBC;
	rijalg.Key = aesKey;
	rijalg.IV = iv;

	ICryptoTransform encryptor = rijalg.CreateEncryptor(rijalg.Key, rijalg.IV);
	return encryptor.TransformFinalBlock(bytes, 0, bytes.Length);
}
  • iv是長度為16的字節(jié)數(shù)組,里邊都是默認(rèn)值0。
  • aeskey是一個長度為32的字節(jié)數(shù)組,不過計算的時候準(zhǔn)備的是長度為40的字節(jié)數(shù)組,需要截一下。
  • Padding需要設(shè)置為PaddingMode.None,默認(rèn)的不是這個。

其它就沒什么好說的了。

為了不那么單調(diào),來一張RDManger的使用界面:

到此這篇關(guān)于C#生成ppk文件的文章就介紹到這了。希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • C#如何Task執(zhí)行任務(wù),等待任務(wù)完成

    C#如何Task執(zhí)行任務(wù),等待任務(wù)完成

    這篇文章主要介紹了C#如何Task執(zhí)行任務(wù),等待任務(wù)完成,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • c# 委托詳解

    c# 委托詳解

    本文將通過實例解析對c# 委托進(jìn)行詳細(xì)介紹,具有很好的參考價值,下面跟著小編一起來看下吧
    2017-02-02
  • C#中Lambda表達(dá)式的用法

    C#中Lambda表達(dá)式的用法

    這篇文章介紹了C#中Lambda表達(dá)式的用法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-05-05
  • C#實現(xiàn)拆分合并Word表格中的單元格

    C#實現(xiàn)拆分合并Word表格中的單元格

    我們在使用Word制作表格時,由于表格較為復(fù)雜,只是簡單的插入行、列并不能滿足我們的需要。要做一個完整的表格,很多時候需要將單元格進(jìn)行拆分或者合并。本文將詳細(xì)為您介紹在Word表格中拆分或合并單元格的思路及方法,希望對大家有所幫助
    2022-12-12
  • C#利用RabbitMQ實現(xiàn)點對點消息傳輸

    C#利用RabbitMQ實現(xiàn)點對點消息傳輸

    RabbitMQ做為消息代理,負(fù)責(zé)接收和轉(zhuǎn)發(fā)消息,可以將RabbitMQ比喻為一個郵筒、一個郵局和一個郵遞員。本文主要以一個簡單的小例子,簡述RabbitMQ實現(xiàn)消息傳輸?shù)南嚓P(guān)內(nèi)容,僅供學(xué)習(xí)分享使用,如有不足之處,還請指正。
    2021-05-05
  • c#中LINQ的基本用法(二)

    c#中LINQ的基本用法(二)

    這篇文章介紹了c#中LINQ的基本用法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下的相關(guān)資料
    2022-04-04
  • C#比較時間大小的方法總結(jié)

    C#比較時間大小的方法總結(jié)

    在本篇內(nèi)容里小編給大家分享的是關(guān)于C#比較時間大小的方法總結(jié),對此有需要的朋友們可以學(xué)習(xí)下。
    2018-12-12
  • 輕松學(xué)習(xí)C#的運算符

    輕松學(xué)習(xí)C#的運算符

    輕松學(xué)習(xí)C#的運算符,對C#的運算符感興趣的朋友可以參考本篇文章,幫助大家更靈活的運用C#的運算符
    2015-11-11
  • C#實現(xiàn)Log4Net日志分類和自動維護(hù)實例

    C#實現(xiàn)Log4Net日志分類和自動維護(hù)實例

    這篇文章主要介紹了C#實現(xiàn)Log4Net日志分類和自動維護(hù),實例講述了Log4Net日志分類和自動維護(hù)的實現(xiàn)方法,并提供了完整的實例供大家參考學(xué)習(xí),需要的朋友可以參考下
    2014-10-10
  • 解析C#設(shè)計模式編程中備忘錄模式的運用

    解析C#設(shè)計模式編程中備忘錄模式的運用

    這篇文章主要介紹了C#設(shè)計模式編程中備忘錄模式的運用,備忘錄模式用來保存與對象有關(guān)的數(shù)據(jù)用以在將來對對象進(jìn)行復(fù)原,需要的朋友可以參考下
    2016-02-02

最新評論