11using System ;
22using System . Collections ;
3+ using System . Diagnostics ;
34using System . IO ;
5+ using Org . BouncyCastle . Asn1 ;
46using Org . BouncyCastle . Asn1 . Misc ;
57using Org . BouncyCastle . Asn1 . X9 ;
68using Org . BouncyCastle . Crypto ;
9+ using Org . BouncyCastle . Crypto . EC ;
710using Org . BouncyCastle . Crypto . Generators ;
811using Org . BouncyCastle . Crypto . Parameters ;
912using Org . BouncyCastle . Math ;
@@ -57,6 +60,10 @@ internal PgpSecretKey(
5760 ECPrivateKeyParameters ecK = ( ECPrivateKeyParameters ) privKey . Key ;
5861 secKey = new ECSecretBcpgKey ( ecK . D ) ;
5962 break ;
63+ case PublicKeyAlgorithmTag . EdDsa :
64+ Ed25519PrivateKeyParameters edK = ( Ed25519PrivateKeyParameters ) privKey . Key ;
65+ secKey = new ECSecretBcpgKey ( new BigInteger ( 1 , edK . GetEncoded ( ) ) ) ;
66+ break ;
6067 case PublicKeyAlgorithmTag . ElGamalEncrypt :
6168 case PublicKeyAlgorithmTag . ElGamalGeneral :
6269 ElGamalPrivateKeyParameters esK = ( ElGamalPrivateKeyParameters ) privKey . Key ;
@@ -1111,24 +1118,26 @@ public static PgpSecretKey ParseSecretKeyFromSExprRaw(Stream inputStream, byte[]
11111118
11121119 internal static PgpSecretKey DoParseSecretKeyFromSExpr ( Stream inputStream , byte [ ] rawPassPhrase , bool clearPassPhrase , PgpPublicKey pubKey )
11131120 {
1114- SXprUtilities . SkipOpenParenthesis ( inputStream ) ;
1121+ SXprUtilities reader = new SXprUtilities ( inputStream ) ;
1122+
1123+ reader . SkipOpenParenthesis ( ) ;
11151124
1116- string type = SXprUtilities . ReadString ( inputStream , inputStream . ReadByte ( ) ) ;
1125+ string type = reader . ReadString ( ) ;
11171126 if ( type . Equals ( "protected-private-key" ) )
11181127 {
1119- SXprUtilities . SkipOpenParenthesis ( inputStream ) ;
1128+ reader . SkipOpenParenthesis ( ) ;
11201129
11211130 string curveName ;
11221131
1123- string keyType = SXprUtilities . ReadString ( inputStream , inputStream . ReadByte ( ) ) ;
1132+ string keyType = reader . ReadString ( ) ;
11241133 if ( keyType . Equals ( "ecc" ) )
11251134 {
1126- SXprUtilities . SkipOpenParenthesis ( inputStream ) ;
1135+ reader . SkipOpenParenthesis ( ) ;
11271136
1128- string curveID = SXprUtilities . ReadString ( inputStream , inputStream . ReadByte ( ) ) ;
1129- curveName = SXprUtilities . ReadString ( inputStream , inputStream . ReadByte ( ) ) ;
1137+ string curveID = reader . ReadString ( ) ;
1138+ curveName = reader . ReadString ( ) ;
11301139
1131- SXprUtilities . SkipCloseParenthesis ( inputStream ) ;
1140+ reader . SkipCloseParenthesis ( ) ;
11321141 }
11331142 else
11341143 {
@@ -1137,21 +1146,21 @@ internal static PgpSecretKey DoParseSecretKeyFromSExpr(Stream inputStream, byte[
11371146
11381147 byte [ ] qVal ;
11391148
1140- SXprUtilities . SkipOpenParenthesis ( inputStream ) ;
1149+ reader . SkipOpenParenthesis ( ) ;
11411150
1142- type = SXprUtilities . ReadString ( inputStream , inputStream . ReadByte ( ) ) ;
1151+ type = reader . ReadString ( ) ;
11431152 if ( type . Equals ( "q" ) )
11441153 {
1145- qVal = SXprUtilities . ReadBytes ( inputStream , inputStream . ReadByte ( ) ) ;
1154+ qVal = reader . ReadBytes ( ) ;
11461155 }
11471156 else
11481157 {
11491158 throw new PgpException ( "no q value found" ) ;
11501159 }
11511160
1152- SXprUtilities . SkipCloseParenthesis ( inputStream ) ;
1161+ reader . SkipCloseParenthesis ( ) ;
11531162
1154- byte [ ] dValue = GetDValue ( inputStream , rawPassPhrase , clearPassPhrase , curveName ) ;
1163+ byte [ ] dValue = GetDValue ( reader , rawPassPhrase , clearPassPhrase , curveName ) ;
11551164 // TODO: check SHA-1 hash.
11561165
11571166 return new PgpSecretKey ( new SecretKeyPacket ( pubKey . PublicKeyPacket , SymmetricKeyAlgorithmTag . Null , null , null ,
@@ -1170,7 +1179,7 @@ internal static PgpSecretKey DoParseSecretKeyFromSExpr(Stream inputStream, byte[
11701179 /// </remarks>
11711180 public static PgpSecretKey ParseSecretKeyFromSExpr ( Stream inputStream , char [ ] passPhrase )
11721181 {
1173- return DoParseSecretKeyFromSExpr ( inputStream , PgpUtilities . EncodePassPhrase ( passPhrase , false ) , true ) ;
1182+ return DoParseSecretKeyFromSExpr ( new SXprUtilities ( inputStream ) , PgpUtilities . EncodePassPhrase ( passPhrase , false ) , true ) ;
11741183 }
11751184
11761185 /// <summary>
@@ -1181,7 +1190,7 @@ public static PgpSecretKey ParseSecretKeyFromSExpr(Stream inputStream, char[] pa
11811190 /// </remarks>
11821191 public static PgpSecretKey ParseSecretKeyFromSExprUtf8 ( Stream inputStream , char [ ] passPhrase )
11831192 {
1184- return DoParseSecretKeyFromSExpr ( inputStream , PgpUtilities . EncodePassPhrase ( passPhrase , true ) , true ) ;
1193+ return DoParseSecretKeyFromSExpr ( new SXprUtilities ( inputStream ) , PgpUtilities . EncodePassPhrase ( passPhrase , true ) , true ) ;
11851194 }
11861195
11871196 /// <summary>
@@ -1192,63 +1201,84 @@ public static PgpSecretKey ParseSecretKeyFromSExprUtf8(Stream inputStream, char[
11921201 /// </remarks>
11931202 public static PgpSecretKey ParseSecretKeyFromSExprRaw ( Stream inputStream , byte [ ] rawPassPhrase )
11941203 {
1195- return DoParseSecretKeyFromSExpr ( inputStream , rawPassPhrase , false ) ;
1204+ return DoParseSecretKeyFromSExpr ( new SXprUtilities ( inputStream ) , rawPassPhrase , false ) ;
11961205 }
11971206
11981207 /// <summary>
11991208 /// Parse a secret key from one of the GPG S expression keys.
12001209 /// </summary>
1201- internal static PgpSecretKey DoParseSecretKeyFromSExpr ( Stream inputStream , byte [ ] rawPassPhrase , bool clearPassPhrase )
1210+ internal static PgpSecretKey DoParseSecretKeyFromSExpr ( SXprUtilities reader , byte [ ] rawPassPhrase , bool clearPassPhrase )
12021211 {
1203- SXprUtilities . SkipOpenParenthesis ( inputStream ) ;
1212+ reader . SkipOpenParenthesis ( ) ;
12041213
1205- string type = SXprUtilities . ReadString ( inputStream , inputStream . ReadByte ( ) ) ;
1214+ string type = reader . ReadString ( ) ;
12061215 if ( type . Equals ( "protected-private-key" ) )
12071216 {
1208- SXprUtilities . SkipOpenParenthesis ( inputStream ) ;
1217+ reader . SkipOpenParenthesis ( ) ;
12091218
12101219 string curveName ;
1220+ DerObjectIdentifier curveOid ;
12111221
1212- string keyType = SXprUtilities . ReadString ( inputStream , inputStream . ReadByte ( ) ) ;
1222+ string keyType = reader . ReadString ( ) ;
12131223 if ( keyType . Equals ( "ecc" ) )
12141224 {
1215- SXprUtilities . SkipOpenParenthesis ( inputStream ) ;
1225+ reader . SkipOpenParenthesis ( ) ;
12161226
1217- string curveID = SXprUtilities . ReadString ( inputStream , inputStream . ReadByte ( ) ) ;
1218- curveName = SXprUtilities . ReadString ( inputStream , inputStream . ReadByte ( ) ) ;
1227+ string curveID = reader . ReadString ( ) ;
1228+ curveName = reader . ReadString ( ) ;
12191229
12201230 if ( Platform . StartsWith ( curveName , "NIST " ) )
12211231 {
12221232 curveName = curveName . Substring ( "NIST " . Length ) ;
12231233 }
12241234
1225- SXprUtilities . SkipCloseParenthesis ( inputStream ) ;
1235+ curveOid = ECNamedCurveTable . GetOid ( curveName ) ;
1236+ if ( curveOid == null )
1237+ {
1238+ curveOid = CustomNamedCurves . GetOid ( curveName ) ;
1239+ }
1240+ if ( curveOid == null )
1241+ {
1242+ throw new PgpException ( "unknown curve" ) ;
1243+ }
1244+
1245+ reader . SkipCloseParenthesis ( ) ;
12261246 }
12271247 else
12281248 {
12291249 throw new PgpException ( "no curve details found" ) ;
12301250 }
12311251
12321252 byte [ ] qVal ;
1253+ string flags = null ;
12331254
1234- SXprUtilities . SkipOpenParenthesis ( inputStream ) ;
1255+ reader . SkipOpenParenthesis ( ) ;
12351256
1236- type = SXprUtilities . ReadString ( inputStream , inputStream . ReadByte ( ) ) ;
1257+ type = reader . ReadString ( ) ;
1258+ if ( type == "flags" )
1259+ {
1260+ // Skip over flags
1261+ flags = reader . ReadString ( ) ;
1262+ reader . SkipCloseParenthesis ( ) ;
1263+ reader . SkipOpenParenthesis ( ) ;
1264+ type = reader . ReadString ( ) ;
1265+ }
12371266 if ( type . Equals ( "q" ) )
12381267 {
1239- qVal = SXprUtilities . ReadBytes ( inputStream , inputStream . ReadByte ( ) ) ;
1268+ qVal = reader . ReadBytes ( ) ;
12401269 }
12411270 else
12421271 {
12431272 throw new PgpException ( "no q value found" ) ;
12441273 }
12451274
1246- PublicKeyPacket pubPacket = new PublicKeyPacket ( PublicKeyAlgorithmTag . ECDsa , DateTime . UtcNow ,
1247- new ECDsaPublicBcpgKey ( ECNamedCurveTable . GetOid ( curveName ) , new BigInteger ( 1 , qVal ) ) ) ;
1275+ PublicKeyPacket pubPacket = new PublicKeyPacket (
1276+ flags == "eddsa" ? PublicKeyAlgorithmTag . EdDsa : PublicKeyAlgorithmTag . ECDsa , DateTime . UtcNow ,
1277+ new ECDsaPublicBcpgKey ( curveOid , new BigInteger ( 1 , qVal ) ) ) ;
12481278
1249- SXprUtilities . SkipCloseParenthesis ( inputStream ) ;
1279+ reader . SkipCloseParenthesis ( ) ;
12501280
1251- byte [ ] dValue = GetDValue ( inputStream , rawPassPhrase , clearPassPhrase , curveName ) ;
1281+ byte [ ] dValue = GetDValue ( reader , rawPassPhrase , clearPassPhrase , curveName ) ;
12521282 // TODO: check SHA-1 hash.
12531283
12541284 return new PgpSecretKey ( new SecretKeyPacket ( pubPacket , SymmetricKeyAlgorithmTag . Null , null , null ,
@@ -1258,51 +1288,68 @@ internal static PgpSecretKey DoParseSecretKeyFromSExpr(Stream inputStream, byte[
12581288 throw new PgpException ( "unknown key type found" ) ;
12591289 }
12601290
1261- private static byte [ ] GetDValue ( Stream inputStream , byte [ ] rawPassPhrase , bool clearPassPhrase , string curveName )
1291+ private static byte [ ] GetDValue ( SXprUtilities reader , byte [ ] rawPassPhrase , bool clearPassPhrase , string curveName )
12621292 {
12631293 string type ;
1264- SXprUtilities . SkipOpenParenthesis ( inputStream ) ;
1294+ reader . SkipOpenParenthesis ( ) ;
12651295
12661296 string protection ;
12671297 S2k s2k ;
12681298 byte [ ] iv ;
12691299 byte [ ] secKeyData ;
12701300
1271- type = SXprUtilities . ReadString ( inputStream , inputStream . ReadByte ( ) ) ;
1301+ type = reader . ReadString ( ) ;
12721302 if ( type . Equals ( "protected" ) )
12731303 {
1274- protection = SXprUtilities . ReadString ( inputStream , inputStream . ReadByte ( ) ) ;
1304+ protection = reader . ReadString ( ) ;
12751305
1276- SXprUtilities . SkipOpenParenthesis ( inputStream ) ;
1306+ reader . SkipOpenParenthesis ( ) ;
12771307
1278- s2k = SXprUtilities . ParseS2k ( inputStream ) ;
1308+ s2k = reader . ParseS2k ( ) ;
12791309
1280- iv = SXprUtilities . ReadBytes ( inputStream , inputStream . ReadByte ( ) ) ;
1310+ iv = reader . ReadBytes ( ) ;
12811311
1282- SXprUtilities . SkipCloseParenthesis ( inputStream ) ;
1312+ reader . SkipCloseParenthesis ( ) ;
12831313
1284- secKeyData = SXprUtilities . ReadBytes ( inputStream , inputStream . ReadByte ( ) ) ;
1314+ secKeyData = reader . ReadBytes ( ) ;
12851315 }
12861316 else
12871317 {
12881318 throw new PgpException ( "protected block not found" ) ;
12891319 }
12901320
1291- // TODO: recognise other algorithms
1292- KeyParameter key = PgpUtilities . DoMakeKeyFromPassPhrase ( SymmetricKeyAlgorithmTag . Aes128 , s2k , rawPassPhrase , clearPassPhrase ) ;
1321+ // Valid values of protection: openpgp-s2k3-sha1-aes-cbc, openpgp-s2k3-ocb-aes, openpgp-native
1322+ byte [ ] data ;
1323+ KeyParameter key ;
1324+
1325+ switch ( protection )
1326+ {
1327+ case "openpgp-s2k3-sha1-aes-cbc" :
1328+ key = PgpUtilities . DoMakeKeyFromPassPhrase ( SymmetricKeyAlgorithmTag . Aes128 , s2k , rawPassPhrase , clearPassPhrase ) ;
1329+ data = RecoverKeyData ( SymmetricKeyAlgorithmTag . Aes128 , "/CBC/NoPadding" , key , iv , secKeyData , 0 , secKeyData . Length ) ;
1330+ break ;
1331+
1332+ case "openpgp-s2k3-ocb-aes" :
1333+ key = PgpUtilities . DoMakeKeyFromPassPhrase ( SymmetricKeyAlgorithmTag . Aes128 , s2k , rawPassPhrase , clearPassPhrase ) ;
1334+ data = RecoverKeyData ( SymmetricKeyAlgorithmTag . Aes128 , "/OCB/NoPadding" , key , iv , secKeyData , 0 , secKeyData . Length ) ;
1335+ break ;
12931336
1294- byte [ ] data = RecoverKeyData ( SymmetricKeyAlgorithmTag . Aes128 , "/CBC/NoPadding" , key , iv , secKeyData , 0 , secKeyData . Length ) ;
1337+ case "openpgp-native" :
1338+ default :
1339+ throw new PgpException ( protection + " key format is not supported yet" ) ;
1340+ }
12951341
12961342 //
12971343 // parse the secret key S-expr
12981344 //
12991345 Stream keyIn = new MemoryStream ( data , false ) ;
13001346
1301- SXprUtilities . SkipOpenParenthesis ( keyIn ) ;
1302- SXprUtilities . SkipOpenParenthesis ( keyIn ) ;
1303- SXprUtilities . SkipOpenParenthesis ( keyIn ) ;
1304- String name = SXprUtilities . ReadString ( keyIn , keyIn . ReadByte ( ) ) ;
1305- return SXprUtilities . ReadBytes ( keyIn , keyIn . ReadByte ( ) ) ;
1347+ reader = new SXprUtilities ( keyIn ) ;
1348+ reader . SkipOpenParenthesis ( ) ;
1349+ reader . SkipOpenParenthesis ( ) ;
1350+ reader . SkipOpenParenthesis ( ) ;
1351+ String name = reader . ReadString ( ) ;
1352+ return reader . ReadBytes ( ) ;
13061353 }
13071354 }
13081355}
0 commit comments