@@ -1113,58 +1113,6 @@ public static PgpSecretKey ParseSecretKeyFromSExprRaw(Stream inputStream, byte[]
11131113 return DoParseSecretKeyFromSExpr ( inputStream , rawPassPhrase , false , pubKey ) ;
11141114 }
11151115
1116- internal static PgpSecretKey DoParseSecretKeyFromSExpr ( Stream inputStream , byte [ ] rawPassPhrase , bool clearPassPhrase , PgpPublicKey pubKey )
1117- {
1118- SXprUtilities . SkipOpenParenthesis ( inputStream ) ;
1119-
1120- string type = SXprUtilities . ReadString ( inputStream , inputStream . ReadByte ( ) ) ;
1121- if ( type . Equals ( "protected-private-key" ) )
1122- {
1123- SXprUtilities . SkipOpenParenthesis ( inputStream ) ;
1124-
1125- string curveName ;
1126-
1127- string keyType = SXprUtilities . ReadString ( inputStream , inputStream . ReadByte ( ) ) ;
1128- if ( keyType . Equals ( "ecc" ) )
1129- {
1130- SXprUtilities . SkipOpenParenthesis ( inputStream ) ;
1131-
1132- string curveID = SXprUtilities . ReadString ( inputStream , inputStream . ReadByte ( ) ) ;
1133- curveName = SXprUtilities . ReadString ( inputStream , inputStream . ReadByte ( ) ) ;
1134-
1135- SXprUtilities . SkipCloseParenthesis ( inputStream ) ;
1136- }
1137- else
1138- {
1139- throw new PgpException ( "no curve details found" ) ;
1140- }
1141-
1142- byte [ ] qVal ;
1143-
1144- SXprUtilities . SkipOpenParenthesis ( inputStream ) ;
1145-
1146- type = SXprUtilities . ReadString ( inputStream , inputStream . ReadByte ( ) ) ;
1147- if ( type . Equals ( "q" ) )
1148- {
1149- qVal = SXprUtilities . ReadBytes ( inputStream , inputStream . ReadByte ( ) ) ;
1150- }
1151- else
1152- {
1153- throw new PgpException ( "no q value found" ) ;
1154- }
1155-
1156- SXprUtilities . SkipCloseParenthesis ( inputStream ) ;
1157-
1158- byte [ ] dValue = GetDValue ( inputStream , rawPassPhrase , clearPassPhrase , curveName ) ;
1159- // TODO: check SHA-1 hash.
1160-
1161- return new PgpSecretKey ( new SecretKeyPacket ( pubKey . PublicKeyPacket , SymmetricKeyAlgorithmTag . Null , null , null ,
1162- new ECSecretBcpgKey ( new MPInteger ( dValue ) ) . GetEncoded ( ) ) , pubKey ) ;
1163- }
1164-
1165- throw new PgpException ( "unknown key type found" ) ;
1166- }
1167-
11681116 /// <summary>
11691117 /// Parse a secret key from one of the GPG S expression keys.
11701118 /// </summary>
@@ -1174,7 +1122,7 @@ internal static PgpSecretKey DoParseSecretKeyFromSExpr(Stream inputStream, byte[
11741122 /// </remarks>
11751123 public static PgpSecretKey ParseSecretKeyFromSExpr ( Stream inputStream , char [ ] passPhrase )
11761124 {
1177- return DoParseSecretKeyFromSExpr ( inputStream , PgpUtilities . EncodePassPhrase ( passPhrase , false ) , true ) ;
1125+ return DoParseSecretKeyFromSExpr ( inputStream , PgpUtilities . EncodePassPhrase ( passPhrase , false ) , true , null ) ;
11781126 }
11791127
11801128 /// <summary>
@@ -1185,7 +1133,7 @@ public static PgpSecretKey ParseSecretKeyFromSExpr(Stream inputStream, char[] pa
11851133 /// </remarks>
11861134 public static PgpSecretKey ParseSecretKeyFromSExprUtf8 ( Stream inputStream , char [ ] passPhrase )
11871135 {
1188- return DoParseSecretKeyFromSExpr ( inputStream , PgpUtilities . EncodePassPhrase ( passPhrase , true ) , true ) ;
1136+ return DoParseSecretKeyFromSExpr ( inputStream , PgpUtilities . EncodePassPhrase ( passPhrase , true ) , true , null ) ;
11891137 }
11901138
11911139 /// <summary>
@@ -1196,31 +1144,33 @@ public static PgpSecretKey ParseSecretKeyFromSExprUtf8(Stream inputStream, char[
11961144 /// </remarks>
11971145 public static PgpSecretKey ParseSecretKeyFromSExprRaw ( Stream inputStream , byte [ ] rawPassPhrase )
11981146 {
1199- return DoParseSecretKeyFromSExpr ( inputStream , rawPassPhrase , false ) ;
1147+ return DoParseSecretKeyFromSExpr ( inputStream , rawPassPhrase , false , null ) ;
12001148 }
12011149
12021150 /// <summary>
12031151 /// Parse a secret key from one of the GPG S expression keys.
12041152 /// </summary>
1205- internal static PgpSecretKey DoParseSecretKeyFromSExpr ( Stream inputStream , byte [ ] rawPassPhrase , bool clearPassPhrase )
1153+ internal static PgpSecretKey DoParseSecretKeyFromSExpr ( Stream inputStream , byte [ ] rawPassPhrase , bool clearPassPhrase , PgpPublicKey pubKey )
12061154 {
1207- SXprUtilities . SkipOpenParenthesis ( inputStream ) ;
1155+ SXprReader reader = new SXprReader ( inputStream ) ;
12081156
1209- string type = SXprUtilities . ReadString ( inputStream , inputStream . ReadByte ( ) ) ;
1157+ reader . SkipOpenParenthesis ( ) ;
1158+
1159+ string type = reader . ReadString ( ) ;
12101160 if ( type . Equals ( "protected-private-key" ) )
12111161 {
1212- SXprUtilities . SkipOpenParenthesis ( inputStream ) ;
1162+ reader . SkipOpenParenthesis ( ) ;
12131163
12141164 string curveName ;
12151165 Oid curveOid ;
12161166
1217- string keyType = SXprUtilities . ReadString ( inputStream , inputStream . ReadByte ( ) ) ;
1167+ string keyType = reader . ReadString ( ) ;
12181168 if ( keyType . Equals ( "ecc" ) )
12191169 {
1220- SXprUtilities . SkipOpenParenthesis ( inputStream ) ;
1170+ reader . SkipOpenParenthesis ( ) ;
12211171
1222- string curveID = SXprUtilities . ReadString ( inputStream , inputStream . ReadByte ( ) ) ;
1223- curveName = SXprUtilities . ReadString ( inputStream , inputStream . ReadByte ( ) ) ;
1172+ string curveID = reader . ReadString ( ) ;
1173+ curveName = reader . ReadString ( ) ;
12241174
12251175 switch ( curveName )
12261176 {
@@ -1230,92 +1180,197 @@ internal static PgpSecretKey DoParseSecretKeyFromSExpr(Stream inputStream, byte[
12301180 case "brainpoolP256r1" : curveOid = new Oid ( "1.3.36.3.3.2.8.1.1.7" ) ; break ;
12311181 case "brainpoolP384r1" : curveOid = new Oid ( "1.3.36.3.3.2.8.1.1.11" ) ; break ;
12321182 case "brainpoolP512r1" : curveOid = new Oid ( "1.3.36.3.3.2.8.1.1.13" ) ; break ;
1233- // FIXME: curve25519
1183+ case "Curve25519" : curveOid = new Oid ( "1.3.6.1.4.1.3029.1.5.1" ) ; break ;
1184+ case "Ed25519" : curveOid = new Oid ( "1.3.6.1.4.1.11591.15.1" ) ; break ;
12341185 default :
12351186 throw new PgpException ( "unknown curve algorithm" ) ;
12361187 }
12371188
1238- SXprUtilities . SkipCloseParenthesis ( inputStream ) ;
1189+ reader . SkipCloseParenthesis ( ) ;
12391190 }
12401191 else
12411192 {
12421193 throw new PgpException ( "no curve details found" ) ;
12431194 }
12441195
12451196 byte [ ] qVal ;
1197+ string flags = null ;
12461198
1247- SXprUtilities . SkipOpenParenthesis ( inputStream ) ;
1199+ reader . SkipOpenParenthesis ( ) ;
12481200
1249- type = SXprUtilities . ReadString ( inputStream , inputStream . ReadByte ( ) ) ;
1201+ type = reader . ReadString ( ) ;
1202+ if ( type == "flags" )
1203+ {
1204+ // Skip over flags
1205+ flags = reader . ReadString ( ) ;
1206+ reader . SkipCloseParenthesis ( ) ;
1207+ reader . SkipOpenParenthesis ( ) ;
1208+ type = reader . ReadString ( ) ;
1209+ }
12501210 if ( type . Equals ( "q" ) )
12511211 {
1252- qVal = SXprUtilities . ReadBytes ( inputStream , inputStream . ReadByte ( ) ) ;
1212+ qVal = reader . ReadBytes ( ) ;
12531213 }
12541214 else
12551215 {
12561216 throw new PgpException ( "no q value found" ) ;
12571217 }
12581218
1259- PublicKeyPacket pubPacket = new PublicKeyPacket ( PublicKeyAlgorithmTag . ECDsa , DateTime . UtcNow ,
1260- new ECDsaPublicBcpgKey ( curveOid , new MPInteger ( qVal ) ) ) ;
1219+ if ( pubKey == null )
1220+ {
1221+ PublicKeyPacket pubPacket = new PublicKeyPacket (
1222+ flags == "eddsa" ? PublicKeyAlgorithmTag . EdDsa : PublicKeyAlgorithmTag . ECDsa , DateTime . UtcNow ,
1223+ new ECDsaPublicBcpgKey ( curveOid , new MPInteger ( qVal ) ) ) ;
1224+ pubKey = new PgpPublicKey ( pubPacket ) ;
1225+ }
12611226
1262- SXprUtilities . SkipCloseParenthesis ( inputStream ) ;
1227+ reader . SkipCloseParenthesis ( ) ;
12631228
1264- byte [ ] dValue = GetDValue ( inputStream , rawPassPhrase , clearPassPhrase , curveName ) ;
1265- // TODO: check SHA-1 hash.
1229+ byte [ ] dValue = GetDValue ( reader , pubKey . PublicKeyPacket , rawPassPhrase , clearPassPhrase , curveName ) ;
12661230
1267- return new PgpSecretKey ( new SecretKeyPacket ( pubPacket , SymmetricKeyAlgorithmTag . Null , null , null ,
1268- new ECSecretBcpgKey ( new MPInteger ( dValue ) ) . GetEncoded ( ) ) , new PgpPublicKey ( pubPacket ) ) ;
1231+ return new PgpSecretKey ( new SecretKeyPacket ( pubKey . PublicKeyPacket , SymmetricKeyAlgorithmTag . Null , null , null ,
1232+ new ECSecretBcpgKey ( new MPInteger ( dValue ) ) . GetEncoded ( ) ) , pubKey ) ;
12691233 }
12701234
12711235 throw new PgpException ( "unknown key type found" ) ;
12721236 }
12731237
1274- private static byte [ ] GetDValue ( Stream inputStream , byte [ ] rawPassPhrase , bool clearPassPhrase , string curveName )
1238+ private static void WriteSExprPublicKey ( SXprWriter writer , PublicKeyPacket pubPacket , string curveName , string protectedAt )
1239+ {
1240+ writer . StartList ( ) ;
1241+ switch ( pubPacket . Algorithm )
1242+ {
1243+ case PublicKeyAlgorithmTag . ECDsa :
1244+ case PublicKeyAlgorithmTag . EdDsa :
1245+ writer . WriteString ( "ecc" ) ;
1246+ writer . StartList ( ) ;
1247+ writer . WriteString ( "curve" ) ;
1248+ writer . WriteString ( curveName ) ;
1249+ writer . EndList ( ) ;
1250+ if ( pubPacket . Algorithm == PublicKeyAlgorithmTag . EdDsa )
1251+ {
1252+ writer . StartList ( ) ;
1253+ writer . WriteString ( "flags" ) ;
1254+ writer . WriteString ( "eddsa" ) ;
1255+ writer . EndList ( ) ;
1256+ }
1257+ writer . StartList ( ) ;
1258+ writer . WriteString ( "q" ) ;
1259+ writer . WriteBytes ( ( ( ECDsaPublicBcpgKey ) pubPacket . Key ) . EncodedPoint . Value ) ;
1260+ writer . EndList ( ) ;
1261+ break ;
1262+
1263+ case PublicKeyAlgorithmTag . RsaEncrypt :
1264+ case PublicKeyAlgorithmTag . RsaSign :
1265+ case PublicKeyAlgorithmTag . RsaGeneral :
1266+ RsaPublicBcpgKey rsaK = ( RsaPublicBcpgKey ) pubPacket . Key ;
1267+ writer . WriteString ( "rsa" ) ;
1268+ writer . StartList ( ) ;
1269+ writer . WriteString ( "n" ) ;
1270+ writer . WriteBytes ( rsaK . Modulus . Value ) ;
1271+ writer . EndList ( ) ;
1272+ writer . StartList ( ) ;
1273+ writer . WriteString ( "e" ) ;
1274+ writer . WriteBytes ( rsaK . PublicExponent . Value ) ;
1275+ writer . EndList ( ) ;
1276+ break ;
1277+
1278+ // TODO: DSA, etc.
1279+ default :
1280+ throw new PgpException ( "unsupported algorithm in S expression" ) ;
1281+ }
1282+
1283+ if ( protectedAt != null )
1284+ {
1285+ writer . StartList ( ) ;
1286+ writer . WriteString ( "protected-at" ) ;
1287+ writer . WriteString ( protectedAt ) ;
1288+ writer . EndList ( ) ;
1289+ }
1290+ writer . EndList ( ) ;
1291+ }
1292+
1293+ private static byte [ ] GetDValue ( SXprReader reader , PublicKeyPacket publicKey , byte [ ] rawPassPhrase , bool clearPassPhrase , string curveName )
12751294 {
12761295 string type ;
1277- SXprUtilities . SkipOpenParenthesis ( inputStream ) ;
1296+ reader . SkipOpenParenthesis ( ) ;
12781297
12791298 string protection ;
1299+ string protectedAt = null ;
12801300 S2k s2k ;
12811301 byte [ ] iv ;
12821302 byte [ ] secKeyData ;
12831303
1284- type = SXprUtilities . ReadString ( inputStream , inputStream . ReadByte ( ) ) ;
1304+ type = reader . ReadString ( ) ;
12851305 if ( type . Equals ( "protected" ) )
12861306 {
1287- protection = SXprUtilities . ReadString ( inputStream , inputStream . ReadByte ( ) ) ;
1307+ protection = reader . ReadString ( ) ;
1308+
1309+ reader . SkipOpenParenthesis ( ) ;
1310+
1311+ s2k = reader . ParseS2k ( ) ;
1312+
1313+ iv = reader . ReadBytes ( ) ;
12881314
1289- SXprUtilities . SkipOpenParenthesis ( inputStream ) ;
1315+ reader . SkipCloseParenthesis ( ) ;
12901316
1291- s2k = SXprUtilities . ParseS2k ( inputStream ) ;
1317+ secKeyData = reader . ReadBytes ( ) ;
12921318
1293- iv = SXprUtilities . ReadBytes ( inputStream , inputStream . ReadByte ( ) ) ;
1319+ reader . SkipCloseParenthesis ( ) ;
12941320
1295- SXprUtilities . SkipCloseParenthesis ( inputStream ) ;
1321+ reader . SkipOpenParenthesis ( ) ;
12961322
1297- secKeyData = SXprUtilities . ReadBytes ( inputStream , inputStream . ReadByte ( ) ) ;
1323+ if ( reader . ReadString ( ) . Equals ( "protected-at" ) )
1324+ {
1325+ protectedAt = reader . ReadString ( ) ;
1326+ }
12981327 }
12991328 else
13001329 {
13011330 throw new PgpException ( "protected block not found" ) ;
13021331 }
13031332
1304- // TODO: recognise other algorithms
1305- byte [ ] key = PgpUtilities . DoMakeKeyFromPassPhrase ( SymmetricKeyAlgorithmTag . Aes128 , s2k , rawPassPhrase , clearPassPhrase ) ;
1333+ byte [ ] data ;
1334+ byte [ ] key ;
1335+
1336+ switch ( protection )
1337+ {
1338+ case "openpgp-s2k3-sha1-aes256-cbc" :
1339+ case "openpgp-s2k3-sha1-aes-cbc" :
1340+ SymmetricKeyAlgorithmTag symmAlg =
1341+ protection . Equals ( "openpgp-s2k3-sha1-aes256-cbc" ) ? SymmetricKeyAlgorithmTag . Aes256 : SymmetricKeyAlgorithmTag . Aes128 ;
1342+ key = PgpUtilities . DoMakeKeyFromPassPhrase ( symmAlg , s2k , rawPassPhrase , clearPassPhrase ) ;
1343+ data = RecoverKeyData ( symmAlg , CipherMode . CBC , key , iv , secKeyData , 0 , secKeyData . Length ) ;
1344+ // TODO: check SHA-1 hash.
1345+ break ;
13061346
1307- byte [ ] data = RecoverKeyData ( SymmetricKeyAlgorithmTag . Aes128 , CipherMode . CBC , key , iv , secKeyData , 0 , secKeyData . Length ) ;
1347+ case "openpgp-s2k3-ocb-aes" :
1348+ MemoryStream aad = new MemoryStream ( ) ;
1349+ WriteSExprPublicKey ( new SXprWriter ( aad ) , publicKey , curveName , protectedAt ) ;
1350+ key = PgpUtilities . DoMakeKeyFromPassPhrase ( SymmetricKeyAlgorithmTag . Aes128 , s2k , rawPassPhrase , clearPassPhrase ) ;
1351+ /*IBufferedCipher c = CipherUtilities.GetCipher("AES/OCB");
1352+ c.Init(false, new AeadParameters(key, 128, iv, aad.ToArray()));
1353+ data = c.DoFinal(secKeyData, 0, secKeyData.Length);*/
1354+ // TODO: AES/OCB support
1355+ throw new NotImplementedException ( ) ;
1356+ break ;
1357+
1358+ case "openpgp-native" :
1359+ default :
1360+ throw new PgpException ( protection + " key format is not supported yet" ) ;
1361+ }
13081362
13091363 //
13101364 // parse the secret key S-expr
13111365 //
13121366 Stream keyIn = new MemoryStream ( data , false ) ;
13131367
1314- SXprUtilities . SkipOpenParenthesis ( keyIn ) ;
1315- SXprUtilities . SkipOpenParenthesis ( keyIn ) ;
1316- SXprUtilities . SkipOpenParenthesis ( keyIn ) ;
1317- String name = SXprUtilities . ReadString ( keyIn , keyIn . ReadByte ( ) ) ;
1318- return SXprUtilities . ReadBytes ( keyIn , keyIn . ReadByte ( ) ) ;
1368+ reader = new SXprReader ( keyIn ) ;
1369+ reader . SkipOpenParenthesis ( ) ;
1370+ reader . SkipOpenParenthesis ( ) ;
1371+ reader . SkipOpenParenthesis ( ) ;
1372+ String name = reader . ReadString ( ) ;
1373+ return reader . ReadBytes ( ) ;
13191374 }
13201375 }
13211376}
0 commit comments